#! perl -slw use strict; use Benchmark::Timer; my $T = new Benchmark::Timer; use List::Util qw[ sum reduce max ]; our( $a, $b ); sub factors{ 2 .. $_[ 0 ] } sub normalise { my( $s, $n ) = @{+shift }; while( 1 ) { if( $n > 1.0 ) { $n /= 10; $s++; redo; } elsif( $n < 0.1 ) { $n *= 10; $s--; redo; } else { last } } return [ $s, $n ]; } sub sProduct{ @{ reduce{ $a->[ 0 ] += $b->[ 0 ]; $a->[ 1 ] *= $b->[ 1 ]; normalise( $a ); } @_ } } sub sProdRange { map{ reduce{ $a->[ 1 ] *= $b; normalise( $a ); } [ 0, 1 ], $_->[ 0 ] .. $_->[ 1 ] } @_; } sub reduceRanges{ our( @v, @s ); local( *v, *s ) = @_; @v = sort{ $b <=> $a } @v; @s = sort{ $b <=> $a } @s; for my $i ( 0 .. max( $#v, $#s ) ) { $s[$i]=1 unless defined $s[$i]; $v[$i]=1 unless defined $v[$i]; my $cmp = $v[$i] <=> $s[$i]; unless( $cmp ) { $s[$i] = [ 1, 1 ]; $v[$i] = [ 1, 1 ]; } elsif( $cmp < 0 ) { $s[$i] = [ $s[$i] - ( $s[$i] - 1 - $v[$i] ), $s[$i] ]; $v[$i] = [ 1, 1 ]; } else { $v[$i] = [ $v[$i] - ( $v[$i] - 1 - $s[$i] ), $v[$i] ]; $s[$i] = [ 1, 1 ]; } } return \@v, \@s; } sub FET6 { my @data = @_; return unless @data == 4; my @C = ( sum( @data[ 0, 2 ] ), sum( @data[ 1, 3 ] ) ); my @R = ( sum( @data[ 0, 1 ] ), sum( @data[ 2, 3 ] ) ); my $N = sum @C; my( $Vref, $Sref ) = reduceRanges [grep $_, @R, @C], [grep $_, $N, @data]; my( $dScale, $d ) = sProduct sProdRange @$Vref; my( $sScale, $s ) = sProduct sProdRange @$Sref; return ( $d / $s, $dScale - $sScale ); } die "Bad args @ARGV" unless @ARGV == 4; $T->start("[@ARGV]"); printf "%.17fe%d\n", FET6 @ARGV; $T->stop("[@ARGV]"); $T->report; __END__ [ 2:39:39.81] P:\test>FET6 5 0 1 4 0.23809523809523819e-1 1 trial of [5 0 1 4] ( 728us total), 728us/trial [ 2:39:32.26] P:\test>fet6 989 9400 43300 2400 0.80706046478677251e-7029 1 trial of [989 9400 43300 2400] (192.499ms total), 192.499ms/trial [ 2:37:08.39] P:\test>FET6 1e6 2e6 2e6 1e6 2.73353759185676100e-147576 1 trial of [1e6 2e6 2e6 1e6] ( 67.960s total), 67.960s/trial [ 2:39:18.10] P:\test>FET6 1e5 2e5 2e5 1e5 1.32499459649680040e-14760 1 trial of [1e5 2e5 2e5 1e5] ( 6.382s total), 6.382s/trial [ 2:35:53.28] P:\test>FET6 1e6 2e6 2e6 1e6 [1e6 2e6 2e6 1e6] 2.73353759185676100e-147576 1 trial of _default ( 67.887s total), 67.887s/trial