# p prime, p=4k+1, p=a^2+b^2 my $n = 300; # sieve to primes 2..$n my @p = map { 1} 0..$n; for ($i=2;$i<$n;$i++) { if ($p[$i]) { my $m = $n/$i; for ($j=2;$j<=$m;$j++) { $p[$i*$j] = 0; } } } foreach my $q ( grep { $p[$_] } 2..$n ) { findsquare($q) if (($q%4)==1); } sub findsquare($) { my $q = shift; # wilson's theorem to find u, u^2=-1 (mod q) my $u=(F(($q-1)/2,$q))%$q; # find duplication, a*u-b=c*u-d (mod q) my %H = map { $_ => [] } 0..($q-1); my $j = -1; my $fx = int(sqrt($q)); my $fy = int(sqrt($q)/2); PAIR: for (my $x=-$fx;$x<=$fx;$x++) { for (my $y=-$fy;$y<=$fy;$y++) { my $k = ($u*$x-$y)%$q; my $a = $H{$k}; push @$a, [$x,$y]; if ((@$a)>1) { $j = $k; last PAIR; } } } # x=(a-c), y=(d-b), x^2+y^2=x^2+(ux)^2=x^2(1-1)=0 (mod q) my $x = $H{$j}->[0][0]-$H{$j}->[1][0]; my $y = $H{$j}->[0][1]-$H{$j}->[1][1]; $x = -$x if ($x<0); $y = -$y if ($y<0); print "prime $q, sqrt(-1)=$u, $x^2+$y^2=",($x*$x+$y*$y),"\n"; } sub F($$) { return ($_[0])?((($_[0]*F($_[0]-1,$_[1])))%$_[1]):1; }