#!/usr/bin/env perl use strict; use warnings; use feature 'state'; use Sub::Genius; my $NUM_THREADS = 5; 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; }