# perl spectral-norm.pl 5500 # output: 1.274224153 # The Computer Language Benchmarks Game # http://benchmarksgame.alioth.debian.org/ # # Contributed by Andrew Rodland # modified by R. Jelinek # multicore by Mykola Zubach # MCE::Hobo version by Mario Roy use strict; use MCE::Hobo; my $cpus = 4; ## MCE::Util->get_ncpu() || 4; my $n = shift || 500; my @v = multiplyAtAv( multiplyAtAv( multiplyAtAv((1) x $n) ) ); my @u = multiplyAtAv(@v); my ($i, $vBv, $vv) = (0); for my $v (@v) { $vBv += $u[$i++] * $v, $vv += $v ** 2; } printf "%0.9f\n", sqrt($vBv / $vv); sub multiplyAtAv { return multiplyAtv(multiplyAv(@_)); } sub eval_A { use integer; my $div = (($_[0] + $_[1]) * ($_[0] + $_[1] + 1) >> 1) + $_[0] + 1; no integer; 1 / $div; } sub multiplyAv { my($begin, $end, @procs); my $chunk = int($#_ / $cpus) + 1; for($begin = 0; $begin < $#_; $begin = $end + 1) { $end = $begin + $chunk; $end = $#_ if $end > $#_; push @procs, MCE::Hobo->create( sub { my $begin = shift; my $end = shift; return map { my ($i, $sum) = ($_); $sum += eval_A($i, $_) * $_[$_] for (0 .. $#_); $sum; } ($begin .. $end); }, $begin, $end, @_); } return map $_->join, @procs; } sub multiplyAtv { my($begin, $end, @procs); my $chunk = int($#_ / $cpus) + 1; for($begin = 0; $begin < $#_; $begin = $end + 1) { $end = $begin + $chunk; $end = $#_ if $end > $#_; push @procs, MCE::Hobo->create( sub { my $begin = shift; my $end = shift; return map { my ($i, $sum) = ($_); $sum += eval_A($_, $i) * $_[$_] for (0 .. $#_); $sum; } ($begin .. $end); }, $begin, $end, @_); } return map $_->join, @procs; }