#!/usr/bin/perl use warnings; use strict; use Math::Polynomial::Solve qw(quadratic_roots); use Math::Numbers; use Data::Dumper; my $level = 64; my @powers_of_two = (1); push (@powers_of_two, $powers_of_two[-1]*2) while $powers_of_two[-1] < $level; my @numbers = @ARGV; @numbers = (1..$level-1) unless @numbers; for my $number (@numbers) { print "E($number/$level)"; for (1) { my @divisors = Math::Numbers->new($number)->get_divisors(); if (grep({$_ == 2} @divisors)) { # trivial print " = E(" . $number/2 . "/" . $level/2 . ")"; } if ($number < $level/2) { # trivial print " = E($number/" . $level/2 . ") & R"; } if (@divisors > 2) { # not a prime, decompose my ($numerator1) = grep({$_ != 1 && $_ != $number} @divisors); my $numerator2 = $number/$numerator1; my $denominator1 = 2; $denominator1 *= 2 while ($denominator1 < $numerator1); my $denominator2 = $level/$denominator1; if ($denominator2 > $numerator2) { print " = E($numerator1/$denominator1) & E($numerator2/$denominator2)"; } } # prime or failed to decompose nicely, try possible overlaps for (my $overlap = 1; $overlap + $number < 2 * $level; $overlap += 2) { my @o_divisors = sort {$a <=> $b} Math::Numbers->new($overlap)->get_divisors(); for my $numerator1 (@o_divisors) { last if $numerator1 > $overlap/2; my $numerator2 = $overlap/$numerator1; # try to find integer d1, d2 such that n1*n2 = level and n1*d2+n2*d1 = number + overlap my $quad_a = $numerator1; my $quad_b = - ($number + $overlap); my $quad_c = $level * $numerator2; my @roots = quadratic_roots($quad_a, $quad_b, $quad_c); #print "overlap $overlap, n1 $numerator1, roots " . join(',', @roots) . "\n"; for my $root (@roots) { next if ref $root; # complex root $root += 0; next unless grep({$root == $_} @powers_of_two); my ($denominator1, $denominator2) = sort {$a <=> $b} ($root, $level/$root); next if $denominator1 < $numerator1; next if $denominator2 < $numerator2; print " = E($numerator1/$denominator1) | E($numerator2/$denominator2)"; } } } } print "\n"; }