#!/usr/bin/env perl
use strict;
use warnings;
use Sub::Genius;
my $NUM_THREADS = 6;
my $preplan = q{
(
step0
&
step1
&
step2
&
step3
&
step4
&
step5
)
reduce
};
my $final_scope = Sub::Genius->new( preplan => $preplan )->run_any( scope => { sum => 0.0, num_steps => 1_000_000, pi => undef } );
printf qq{pi = %f\n}, $final_scope->{pi};
sub AUTOLOAD {
our $AUTOLOAD;
my $sub = $AUTOLOAD;
$sub =~ s/.*:://;
die if $sub !~ m/^step([\d]+)/;
my $step_id = $1;
# deal with 'step'
my $old_scope = shift;
my $new_scope = _snep( $step_id, $old_scope );
return $new_scope;
}
sub _snep {
my ( $step_id, $scope ) = @_;
$scope->{sum} = _do_calc( $step_id, $scope );
return $scope;
}
sub reduce {
my $scope = shift;
my $num_steps = $scope->{num_steps};
my $step = 1 / $num_steps;
$scope->{pi} = $scope->{sum} * $step;
return $scope;
}
sub _do_calc {
my ( $id, $scope ) = @_;
my $sum = $scope->{sum};
my $num_steps = $scope->{num_steps};
my $step = 1 / $num_steps;
for ( my $i = $id ; $i < $num_steps ; $i += $NUM_THREADS ) {
my $x = ( $i + 0.5 ) * $step;
$sum += 4.0 / ( 1 + $x * $x );
}
return $sum;
}