# 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::Map version by Mario Roy use strict; use MCE::Map; my $n = shift || 500; my $cpus = 4; ## MCE::Util->get_ncpu() || 4; MCE::Map->init( max_workers => $cpus, chunk_size => int(($n - 1) / $cpus) + 1, ); 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); MCE::Map->finish(); 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 @data = @_; return mce_map_s { my ($i, $sum) = ($_); $sum += eval_A($i, $_) * $data[$_] for (0 .. $#data); $sum; } 0, $#data; } sub multiplyAtv { my @data = @_; return mce_map_s { my ($i, $sum) = ($_); $sum += eval_A($_, $i) * $data[$_] for (0 .. $#data); $sum; } 0, $#data; }