package Math::BigPositiveOkayPrecision; use overload '+' => \&add, #'-' => \&sub, '*' => \&mul, '/' => \&div, '**' => \&pow, '^' => \&prd, # $x^$y = factorial($y)/factorial($x) '<<' => \&shl, '>>' => \&shr, '<=>'=> \&cmp, '!' => \&fct, # !$x = factorial($x) '0+' => \&num, '""' => \&str, #'neg'=> \&neg, ; sub new { my $us= shift @_; if( ! @_ ) { die "new() needs an object or a value" if ! ref $us; return bless \( 0+$$us ); } my $val= shift @_; die "Non-positive values not supported yet ($val)" if $val <= 0; return bless \log( $val ); } *Okay::new= \&new; # Until we get a better module name sub mul { my( $x, $y )= @_; $y= $x->new( $y ) if ! ref $y; return bless \( $$x + $$y ); } sub div { my( $x, $y, $rev )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $rev; return bless \( $$x - $$y ); } sub pow { my( $x, $y, $rev )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $rev; return bless \( $$x * exp($$y) ); } sub add { my( $x, $y )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $$y < $$x; return bless \( $$y + log( 1 + exp( $$x - $$y ) ) ); } sub shl { my( $x, $y, $rev )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $rev; return bless \( $$x + exp($$y)*log(2) ); } sub shr { my( $x, $y, $rev )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $rev; return bless \( $$x - exp($$y)*log(2) ); } sub cmp { my( $x, $y, $rev )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $rev; return $$x <=> $$y; } sub prd { my( $x, $y, $rev )= @_; $y= $x->new( $y ) if ! ref $y; ( $x, $y )= ( $y, $x ) if $rev; return bless \0 if $$y < $$x; my $p= $x->new(); my $m= $x + 1; while( $m <= $y ) { $p= $p * $m; $m= $m + 1; } return $p; } sub fct { my( $x )= @_; return 1^$x; } sub num { my( $x )= @_; return exp( $$x ); } sub str { my( $x )= @_; my $exp= int( $$x / log(10) ); my $mant= exp( $$x - log(10)*$exp ); $mant= sprintf "%.10f", $mant; $mant .= $exp ? "e" . $exp : ""; return $mant if 9 < $exp; return 0 + $mant; } __PACKAGE__;