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

📄 bigint.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
📖 第 1 页 / 共 5 页
字号:
    {    ($self,$x,$y) = objectify(2,@_);    }  return $upgrade->bacmp($x,$y) if defined $upgrade &&    ((!$x->isa($self)) || (!$y->isa($self)));  if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))    {    # handle +-inf and NaN    return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));    return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;    return +1;	# inf is always bigger    }  $CALC->_acmp($x->{value},$y->{value});	# lib does only 0,1,-1  }sub badd   {  # add second arg (BINT or string) to first (BINT) (modifies first)  # return result as BINT  # set up parameters  my ($self,$x,$y,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,@r) = objectify(2,@_);    }  return $x if $x->modify('badd');  return $upgrade->badd($x,$y,@r) if defined $upgrade &&    ((!$x->isa($self)) || (!$y->isa($self)));  $r[3] = $y;				# no push!  # inf and NaN handling  if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))    {    # NaN first    return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));    # inf handling    if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))      {      # +inf++inf or -inf+-inf => same, rest is NaN      return $x if $x->{sign} eq $y->{sign};      return $x->bnan();      }    # +-inf + something => +inf    # something +-inf => +-inf    $x->{sign} = $y->{sign}, return $x if $y->{sign} =~ /^[+-]inf$/;    return $x;    }      my ($sx, $sy) = ( $x->{sign}, $y->{sign} ); # get signs  if ($sx eq $sy)      {    $x->{value} = $CALC->_add($x->{value},$y->{value});	# same sign, abs add    $x->{sign} = $sx;    }  else     {    my $a = $CALC->_acmp ($y->{value},$x->{value});	# absolute compare    if ($a > 0)                                 {      #print "swapped sub (a=$a)\n";      $x->{value} = $CALC->_sub($y->{value},$x->{value},1); # abs sub w/ swap      $x->{sign} = $sy;      }     elsif ($a == 0)      {      # speedup, if equal, set result to 0      #print "equal sub, result = 0\n";      $x->{value} = $CALC->_zero();      $x->{sign} = '+';      }    else # a < 0      {      #print "unswapped sub (a=$a)\n";      $x->{value} = $CALC->_sub($x->{value}, $y->{value}); # abs sub      $x->{sign} = $sx;      }    }  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;  $x;  }sub bsub   {  # (BINT or num_str, BINT or num_str) return num_str  # subtract second arg from first, modify first    # set up parameters  my ($self,$x,$y,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,@r) = objectify(2,@_);    }  return $x if $x->modify('bsub');# upgrade done by badd():#  return $upgrade->badd($x,$y,@r) if defined $upgrade &&#   ((!$x->isa($self)) || (!$y->isa($self)));  if ($y->is_zero())    {     $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;    return $x;    }  $y->{sign} =~ tr/+\-/-+/; 	# does nothing for NaN  $x->badd($y,@r); 		# badd does not leave internal zeros  $y->{sign} =~ tr/+\-/-+/; 	# refix $y (does nothing for NaN)  $x;				# already rounded by badd() or no round necc.  }sub binc  {  # increment arg by one  my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);  return $x if $x->modify('binc');  if ($x->{sign} eq '+')    {    $x->{value} = $CALC->_inc($x->{value});    $x->round($a,$p,$r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;    return $x;    }  elsif ($x->{sign} eq '-')    {    $x->{value} = $CALC->_dec($x->{value});    $x->{sign} = '+' if $CALC->_is_zero($x->{value}); # -1 +1 => -0 => +0    $x->round($a,$p,$r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;    return $x;    }  # inf, nan handling etc  $x->badd($self->__one(),$a,$p,$r);		# badd does round  }sub bdec  {  # decrement arg by one  my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);  return $x if $x->modify('bdec');    my $zero = $CALC->_is_zero($x->{value}) && $x->{sign} eq '+';  # <= 0  if (($x->{sign} eq '-') || $zero)     {    $x->{value} = $CALC->_inc($x->{value});    $x->{sign} = '-' if $zero;			# 0 => 1 => -1    $x->{sign} = '+' if $CALC->_is_zero($x->{value}); # -1 +1 => -0 => +0    $x->round($a,$p,$r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;    return $x;    }  # > 0  elsif ($x->{sign} eq '+')    {    $x->{value} = $CALC->_dec($x->{value});    $x->round($a,$p,$r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;    return $x;    }  # inf, nan handling etc  $x->badd($self->__one('-'),$a,$p,$r);			# badd does round  } sub blog  {  # not implemented yet  my ($self,$x,$base,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);   return $upgrade->blog($x,$base,$a,$p,$r) if defined $upgrade;  return $x->bnan();  } sub blcm   {   # (BINT or num_str, BINT or num_str) return BINT  # does not modify arguments, but returns new object  # Lowest Common Multiplicator  my $y = shift; my ($x);  if (ref($y))    {    $x = $y->copy();    }  else    {    $x = $class->new($y);    }  while (@_) { $x = __lcm($x,shift); }   $x;  }sub bgcd   {   # (BINT or num_str, BINT or num_str) return BINT  # does not modify arguments, but returns new object  # GCD -- Euclids algorithm, variant C (Knuth Vol 3, pg 341 ff)  my $y = shift;  $y = __PACKAGE__->new($y) if !ref($y);  my $self = ref($y);  my $x = $y->copy();		# keep arguments  if ($CALC->can('_gcd'))    {    while (@_)      {      $y = shift; $y = $self->new($y) if !ref($y);      next if $y->is_zero();      return $x->bnan() if $y->{sign} !~ /^[+-]$/;	# y NaN?      $x->{value} = $CALC->_gcd($x->{value},$y->{value}); last if $x->is_one();      }    }  else    {    while (@_)      {      $y = shift; $y = $self->new($y) if !ref($y);      $x = __gcd($x,$y->copy()); last if $x->is_one();	# _gcd handles NaN      }     }  $x->babs();  }sub bnot   {  # (num_str or BINT) return BINT  # represent ~x as twos-complement number  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x,$a,$p,$r) = ref($_[0]) ? (undef,@_) : objectify(1,@_);   return $x if $x->modify('bnot');  $x->bneg()->bdec();			# bdec already does round  }# is_foo test routinessub is_zero  {  # return true if arg (BINT or num_str) is zero (array '+', '0')  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);    return 0 if $x->{sign} !~ /^\+$/;			# -, NaN & +-inf aren't  $CALC->_is_zero($x->{value});  }sub is_nan  {  # return true if arg (BINT or num_str) is NaN  my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);  return 1 if $x->{sign} eq $nan;  0;  }sub is_inf  {  # return true if arg (BINT or num_str) is +-inf  my ($self,$x,$sign) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);  $sign = '' if !defined $sign;  return 1 if $sign eq $x->{sign};		# match ("+inf" eq "+inf")  return 0 if $sign !~ /^([+-]|)$/;  if ($sign eq '')    {    return 1 if ($x->{sign} =~ /^[+-]inf$/);     return 0;    }  $sign = quotemeta($sign.'inf');  return 1 if ($x->{sign} =~ /^$sign$/);  0;  }sub is_one  {  # return true if arg (BINT or num_str) is +1  # or -1 if sign is given  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x,$sign) = ref($_[0]) ? (undef,@_) : objectify(1,@_);      $sign = '' if !defined $sign; $sign = '+' if $sign ne '-';   return 0 if $x->{sign} ne $sign; 	# -1 != +1, NaN, +-inf aren't either  $CALC->_is_one($x->{value});  }sub is_odd  {  # return true when arg (BINT or num_str) is odd, false for even  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);  return 0 if $x->{sign} !~ /^[+-]$/;			# NaN & +-inf aren't  $CALC->_is_odd($x->{value});  }sub is_even  {  # return true when arg (BINT or num_str) is even, false for odd  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);  return 0 if $x->{sign} !~ /^[+-]$/;			# NaN & +-inf aren't  $CALC->_is_even($x->{value});  }sub is_positive  {  # return true when arg (BINT or num_str) is positive (>= 0)  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);    return 1 if $x->{sign} =~ /^\+/;  0;  }sub is_negative  {  # return true when arg (BINT or num_str) is negative (< 0)  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);    return 1 if ($x->{sign} =~ /^-/);  0;  }sub is_int  {  # return true when arg (BINT or num_str) is an integer  # always true for BigInt, but different for Floats  # we don't need $self, so undef instead of ref($_[0]) make it slightly faster  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);    $x->{sign} =~ /^[+-]$/ ? 1 : 0;		# inf/-inf/NaN aren't  }###############################################################################sub bmul   {   # multiply two numbers -- stolen from Knuth Vol 2 pg 233  # (BINT or num_str, BINT or num_str) return BINT  # set up parameters  my ($self,$x,$y,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,@r) = objectify(2,@_);    }    return $x if $x->modify('bmul');  return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));  # inf handling  if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))    {    return $x->bnan() if $x->is_zero() || $y->is_zero();    # result will always be +-inf:    # +inf * +/+inf => +inf, -inf * -/-inf => +inf    # +inf * -/-inf => -inf, -inf * +/+inf => -inf    return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);     return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);     return $x->binf('-');    }    return $upgrade->bmul($x,$y,@r)   if defined $upgrade && $y->isa($upgrade);    $r[3] = $y;				# no push here  $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-'; # +1 * +1 or -1 * -1 => +  $x->{value} = $CALC->_mul($x->{value},$y->{value});	# do actual math  $x->{sign} = '+' if $CALC->_is_zero($x->{value}); 	# no -0  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;  $x;  }sub _div_inf  {  # helper function that handles +-inf cases for bdiv()/bmod() to reuse code  my ($self,$x,$y) = @_;  # NaN if x == NaN or y == NaN or x==y==0  return wantarray ? ($x->bnan(),$self->bnan()) : $x->bnan()   if (($x->is_nan() || $y->is_nan())   ||       ($x->is_zero() && $y->is_zero()));   # +-inf / +-inf == NaN, reminder also NaN  if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))    {    return wantarray ? ($x->bnan(),$self->bnan()) : $x->bnan();    }  # x / +-inf => 0, remainder x (works even if x == 0)  if ($y->{sign} =~ /^[+-]inf$/)    {    my $t = $x->copy();		# bzero clobbers up $x    return wantarray ? ($x->bzero(),$t) : $x->bzero()    }    # 5 / 0 => +inf, -6 / 0 => -inf  # +inf / 0 = inf, inf,  and -inf / 0 => -inf, -inf   # exception:   -8 / 0 has remainder -8, not 8  # exception: -inf / 0 has remainder -inf, not inf  if ($y->is_zero())    {    # +-inf / 0 => special case for -inf    return wantarray ?  ($x,$x->copy()) : $x if $x->is_inf();    if (!$x->is_zero() && !$x->is_inf())      {      my $t = $x->copy();		# binf clobbers up $x      return wantarray ?       ($x->binf($x->{sign}),$t) : $x->binf($x->{sign})      }    }    # last case: +-inf / ordinary number  my $sign = '+inf';  $sign = '-inf' if substr($x->{sign},0,1) ne $y->{sign};  $x->{sign} = $sign;  return wantarray ? ($x,$self->bzero()) : $x;  }sub bdiv   {  # (dividend: BINT or num_str, divisor: BINT or num_str) return   # (BINT,BINT) (quo,rem) or BINT (only rem)    # set up parameters  my ($self,$x,$y,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,@r) = objectify(2,@_);    }   return $x if $x->modify('bdiv');  return $self->_div_inf($x,$y)   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());  return $upgrade->bdiv($upgrade->new($x),$y,@r)   if defined $upgrade && !$y->isa($self);  $r[3] = $y;					# no push!  # 0 / something

⌨️ 快捷键说明

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