⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bigint.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
📖 第 1 页 / 共 5 页
字号:
package Math::BigInt;## "Mike had an infinite amount to do and a negative amount of time in which# to do it." - Before and After## The following hash values are used:#   value: unsigned int with actual value (as a Math::BigInt::Calc or similiar)#   sign : +,-,NaN,+inf,-inf#   _a   : accuracy#   _p   : precision#   _f   : flags, used by MBF to flag parts of a float as untouchable# Remember not to take shortcuts ala $xs = $x->{value}; $CALC->foo($xs); since# underlying lib might change the reference!my $class = "Math::BigInt";require 5.005;$VERSION = '1.63';use Exporter;@ISA =       qw( Exporter );@EXPORT_OK = qw( objectify _swap bgcd blcm); use vars qw/$round_mode $accuracy $precision $div_scale $rnd_mode/;use vars qw/$upgrade $downgrade/;use strict;# Inside overload, the first arg is always an object. If the original code had# it reversed (like $x = 2 * $y), then the third paramater indicates this# swapping. To make it work, we use a helper routine which not only reswaps the# params, but also makes a new object in this case. See _swap() for details,# especially the cases of operators with different classes.# For overloaded ops with only one argument we simple use $_[0]->copy() to# preserve the argument.# Thus inheritance of overload operators becomes possible and transparent for# our subclasses without the need to repeat the entire overload section there.use overload'='     =>      sub { $_[0]->copy(); },# '+' and '-' do not use _swap, since it is a triffle slower. If you want to# override _swap (if ever), then override overload of '+' and '-', too!# for sub it is a bit tricky to keep b: b-a => -a+b'-'	=>	sub { my $c = $_[0]->copy; $_[2] ?                   $c->bneg()->badd($_[1]) :                   $c->bsub( $_[1]) },'+'	=>	sub { $_[0]->copy()->badd($_[1]); },# some shortcuts for speed (assumes that reversed order of arguments is routed# to normal '+' and we thus can always modify first arg. If this is changed,# this breaks and must be adjusted.)'+='	=>	sub { $_[0]->badd($_[1]); },'-='	=>	sub { $_[0]->bsub($_[1]); },'*='	=>	sub { $_[0]->bmul($_[1]); },'/='	=>	sub { scalar $_[0]->bdiv($_[1]); },'%='	=>	sub { $_[0]->bmod($_[1]); },'^='	=>	sub { $_[0]->bxor($_[1]); },'&='	=>	sub { $_[0]->band($_[1]); },'|='	=>	sub { $_[0]->bior($_[1]); },'**='	=>	sub { $_[0]->bpow($_[1]); },# not supported by Perl yet'..'	=>	\&_pointpoint,'<=>'	=>	sub { $_[2] ?                      ref($_[0])->bcmp($_[1],$_[0]) :                       $_[0]->bcmp($_[1])},'cmp'	=>	sub {         $_[2] ?                "$_[1]" cmp $_[0]->bstr() :               $_[0]->bstr() cmp "$_[1]" },'log'	=>	sub { $_[0]->copy()->blog(); }, 'int'	=>	sub { $_[0]->copy(); }, 'neg'	=>	sub { $_[0]->copy()->bneg(); }, 'abs'	=>	sub { $_[0]->copy()->babs(); },'sqrt'  =>	sub { $_[0]->copy()->bsqrt(); },'~'	=>	sub { $_[0]->copy()->bnot(); },'*'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->bmul($a[1]); },'/'	=>	sub { my @a = ref($_[0])->_swap(@_);scalar $a[0]->bdiv($a[1]);},'%'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->bmod($a[1]); },'**'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->bpow($a[1]); },'<<'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->blsft($a[1]); },'>>'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->brsft($a[1]); },'&'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->band($a[1]); },'|'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->bior($a[1]); },'^'	=>	sub { my @a = ref($_[0])->_swap(@_); $a[0]->bxor($a[1]); },# can modify arg of ++ and --, so avoid a new-copy for speed, but don't# use $_[0]->__one(), it modifies $_[0] to be 1!'++'	=>	sub { $_[0]->binc() },'--'	=>	sub { $_[0]->bdec() },# if overloaded, O(1) instead of O(N) and twice as fast for small numbers'bool'  =>	sub {  # this kludge is needed for perl prior 5.6.0 since returning 0 here fails :-/  # v5.6.1 dumps on that: return !$_[0]->is_zero() || undef;		    :-(  my $t = !$_[0]->is_zero();  undef $t if $t == 0;  $t;  },# the original qw() does not work with the TIESCALAR below, why?# Order of arguments unsignificant'""' => sub { $_[0]->bstr(); },'0+' => sub { $_[0]->numify(); };############################################################################### global constants, flags and accessoryuse constant MB_NEVER_ROUND => 0x0001;my $NaNOK=1; 				# are NaNs ok?my $nan = 'NaN'; 			# constants for easier lifemy $CALC = 'Math::BigInt::Calc';	# module to do low level mathmy $IMPORT = 0;				# did import() yet?$round_mode = 'even'; # one of 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'$accuracy   = undef;$precision  = undef;$div_scale  = 40;$upgrade = undef;			# default is no upgrade$downgrade = undef;			# default is no downgrade############################################################################### the old code had $rnd_mode, so we need to support it, too$rnd_mode   = 'even';sub TIESCALAR  { my ($class) = @_; bless \$round_mode, $class; }sub FETCH      { return $round_mode; }sub STORE      { $rnd_mode = $_[0]->round_mode($_[1]); }BEGIN { tie $rnd_mode, 'Math::BigInt'; }############################################################################## sub round_mode  {  no strict 'refs';  # make Class->round_mode() work  my $self = shift;  my $class = ref($self) || $self || __PACKAGE__;  if (defined $_[0])    {    my $m = shift;    die "Unknown round mode $m"     if $m !~ /^(even|odd|\+inf|\-inf|zero|trunc)$/;    return ${"${class}::round_mode"} = $m;    }  return ${"${class}::round_mode"};  }sub upgrade  {  no strict 'refs';  # make Class->upgrade() work  my $self = shift;  my $class = ref($self) || $self || __PACKAGE__;  # need to set new value?  if (@_ > 0)    {    my $u = shift;    return ${"${class}::upgrade"} = $u;    }  return ${"${class}::upgrade"};  }sub downgrade  {  no strict 'refs';  # make Class->downgrade() work  my $self = shift;  my $class = ref($self) || $self || __PACKAGE__;  # need to set new value?  if (@_ > 0)    {    my $u = shift;    return ${"${class}::downgrade"} = $u;    }  return ${"${class}::downgrade"};  }sub div_scale  {  no strict 'refs';  # make Class->round_mode() work  my $self = shift;  my $class = ref($self) || $self || __PACKAGE__;  if (defined $_[0])    {    die ('div_scale must be greater than zero') if $_[0] < 0;    ${"${class}::div_scale"} = shift;    }  return ${"${class}::div_scale"};  }sub accuracy  {  # $x->accuracy($a);		ref($x)	$a  # $x->accuracy();		ref($x)  # Class->accuracy();		class  # Class->accuracy($a);	class $a  my $x = shift;  my $class = ref($x) || $x || __PACKAGE__;  no strict 'refs';  # need to set new value?  if (@_ > 0)    {    my $a = shift;    die ('accuracy must not be zero') if defined $a && $a == 0;    if (ref($x))      {      # $object->accuracy() or fallback to global      $x->bround($a) if defined $a;      $x->{_a} = $a;			# set/overwrite, even if not rounded      $x->{_p} = undef;			# clear P      }    else      {      # set global      ${"${class}::accuracy"} = $a;      ${"${class}::precision"} = undef;	# clear P      }    return $a;				# shortcut    }  my $r;  # $object->accuracy() or fallback to global  $r = $x->{_a} if ref($x);  # but don't return global undef, when $x's accuracy is 0!  $r = ${"${class}::accuracy"} if !defined $r;  $r;  } sub precision  {  # $x->precision($p);		ref($x)	$p  # $x->precision();		ref($x)  # Class->precision();		class  # Class->precision($p);	class $p  my $x = shift;  my $class = ref($x) || $x || __PACKAGE__;  no strict 'refs';  # need to set new value?  if (@_ > 0)    {    my $p = shift;    if (ref($x))      {      # $object->precision() or fallback to global      $x->bfround($p) if defined $p;      $x->{_p} = $p;			# set/overwrite, even if not rounded      $x->{_a} = undef;			# clear A      }    else      {      # set global      ${"${class}::precision"} = $p;      ${"${class}::accuracy"} = undef;	# clear A      }    return $p;				# shortcut    }  my $r;  # $object->precision() or fallback to global  $r = $x->{_p} if ref($x);  # but don't return global undef, when $x's precision is 0!  $r = ${"${class}::precision"} if !defined $r;  $r;  } sub config  {  # return (later set?) configuration data as hash ref  my $class = shift || 'Math::BigInt';  no strict 'refs';  my $lib = $CALC;  my $cfg = {    lib => $lib,    lib_version => ${"${lib}::VERSION"},    class => $class,    };  foreach (   qw/upgrade downgrade precision accuracy round_mode VERSION div_scale/)    {    $cfg->{lc($_)} = ${"${class}::$_"};    };  $cfg;  }sub _scale_a  {   # select accuracy parameter based on precedence,  # used by bround() and bfround(), may return undef for scale (means no op)  my ($x,$s,$m,$scale,$mode) = @_;  $scale = $x->{_a} if !defined $scale;  $scale = $s if (!defined $scale);  $mode = $m if !defined $mode;  return ($scale,$mode);  }sub _scale_p  {   # select precision parameter based on precedence,  # used by bround() and bfround(), may return undef for scale (means no op)  my ($x,$s,$m,$scale,$mode) = @_;  $scale = $x->{_p} if !defined $scale;  $scale = $s if (!defined $scale);  $mode = $m if !defined $mode;  return ($scale,$mode);  }############################################################################### constructorssub copy  {  my ($c,$x);  if (@_ > 1)    {    # if two arguments, the first one is the class to "swallow" subclasses    ($c,$x) = @_;    }  else    {    $x = shift;    $c = ref($x);    }  return unless ref($x); # only for objects  my $self = {}; bless $self,$c;  my $r;  foreach my $k (keys %$x)    {    if ($k eq 'value')      {      $self->{value} = $CALC->_copy($x->{value}); next;      }    if (!($r = ref($x->{$k})))      {      $self->{$k} = $x->{$k}; next;      }    if ($r eq 'SCALAR')      {      $self->{$k} = \${$x->{$k}};      }    elsif ($r eq 'ARRAY')      {      $self->{$k} = [ @{$x->{$k}} ];      }    elsif ($r eq 'HASH')      {      # only one level deep!      foreach my $h (keys %{$x->{$k}})        {        $self->{$k}->{$h} = $x->{$k}->{$h};        }      }    else # normal ref      {      my $xk = $x->{$k};      if ($xk->can('copy'))        {	$self->{$k} = $xk->copy();        }      else	{	$self->{$k} = $xk->new($xk);	}      }    }  $self;  }sub new   {  # create a new BigInt object from a string or another BigInt object.   # see hash keys documented at top  # the argument could be an object, so avoid ||, && etc on it, this would  # cause costly overloaded code to be called. The only allowed ops are  # ref() and defined.  my ($class,$wanted,$a,$p,$r) = @_;   # avoid numify-calls by not using || on $wanted!  return $class->bzero($a,$p) if !defined $wanted;	# default to 0  return $class->copy($wanted,$a,$p,$r)   if ref($wanted) && $wanted->isa($class);		# MBI or subclass  $class->import() if $IMPORT == 0;		# make require work    my $self = bless {}, $class;  # shortcut for "normal" numbers  if ((!ref $wanted) && ($wanted =~ /^([+-]?)[1-9][0-9]*\z/))    {    $self->{sign} = $1 || '+';    my $ref = \$wanted;    if ($wanted =~ /^[+-]/)     {      # remove sign without touching wanted to make it work with constants      my $t = $wanted; $t =~ s/^[+-]//; $ref = \$t;      }    $self->{value} = $CALC->_new($ref);    no strict 'refs';    if ( (defined $a) || (defined $p)         || (defined ${"${class}::precision"})        || (defined ${"${class}::accuracy"})        )      {      $self->round($a,$p,$r) unless (@_ == 4 && !defined $a && !defined $p);      }    return $self;    }  # handle '+inf', '-inf' first  if ($wanted =~ /^[+-]?inf$/)    {    $self->{value} = $CALC->_zero();    $self->{sign} = $wanted; $self->{sign} = '+inf' if $self->{sign} eq 'inf';    return $self;    }  # split str in m mantissa, e exponent, i integer, f fraction, v value, s sign  my ($mis,$miv,$mfv,$es,$ev) = _split(\$wanted);  if (!ref $mis)    {    die "$wanted is not a number initialized to $class" if !$NaNOK;    #print "NaN 1\n";    $self->{value} = $CALC->_zero();    $self->{sign} = $nan;    return $self;    }  if (!ref $miv)    {    # _from_hex or _from_bin    $self->{value} = $mis->{value};    $self->{sign} = $mis->{sign};    return $self;	# throw away $mis    }  # make integer from mantissa by adjusting exp, then convert to bigint  $self->{sign} = $$mis;			# store sign  $self->{value} = $CALC->_zero();		# for all the NaN cases

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -