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

📄 bigint.pm

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 PM
📖 第 1 页 / 共 5 页
字号:
  # inf handling  if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))    {    if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))      {      # +-inf ** +-inf      return $x->bnan();      }    # +-inf ** Y    if ($x->{sign} =~ /^[+-]inf/)      {      # +inf ** 0 => NaN      return $x->bnan() if $y->is_zero();      # -inf ** -1 => 1/inf => 0      return $x->bzero() if $y->is_one('-') && $x->is_negative();      # +inf ** Y => inf      return $x if $x->{sign} eq '+inf';      # -inf ** Y => -inf if Y is odd      return $x if $y->is_odd();      return $x->babs();      }    # X ** +-inf    # 1 ** +inf => 1    return $x if $x->is_one();        # 0 ** inf => 0    return $x if $x->is_zero() && $y->{sign} =~ /^[+]/;    # 0 ** -inf => inf    return $x->binf() if $x->is_zero();    # -1 ** -inf => NaN    return $x->bnan() if $x->is_one('-') && $y->{sign} =~ /^[-]/;    # -X ** -inf => 0    return $x->bzero() if $x->{sign} eq '-' && $y->{sign} =~ /^[-]/;    # -1 ** inf => NaN    return $x->bnan() if $x->{sign} eq '-';    # X ** inf => inf    return $x->binf() if $y->{sign} =~ /^[+]/;    # X ** -inf => 0    return $x->bzero();    }  return $upgrade->bpow($upgrade->new($x),$y,@r)   if defined $upgrade && (!$y->isa($self) || $y->{sign} eq '-');  $r[3] = $y;					# no push!  # cases 0 ** Y, X ** 0, X ** 1, 1 ** Y are handled by Calc or Emu  my $new_sign = '+';  $new_sign = $y->is_odd() ? '-' : '+' if ($x->{sign} ne '+');   # 0 ** -7 => ( 1 / (0 ** 7)) => 1 / 0 => +inf   return $x->binf()     if $y->{sign} eq '-' && $x->{sign} eq '+' && $CALC->_is_zero($x->{value});  # 1 ** -y => 1 / (1 ** |y|)  # so do test for negative $y after above's clause  return $x->bnan() if $y->{sign} eq '-' && !$CALC->_is_one($x->{value});  $x->{value} = $CALC->_pow($x->{value},$y->{value});  $x->{sign} = $new_sign;  $x->{sign} = '+' if $CALC->_is_zero($y->{value});  $x->round(@r);  }sub blsft   {  # (BINT or num_str, BINT or num_str) return BINT  # compute x << y, base n, y >= 0   # set up parameters  my ($self,$x,$y,$n,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,$n,@r) = objectify(2,@_);    }  return $x if $x->modify('blsft');  return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);  return $x->round(@r) if $y->is_zero();  $n = 2 if !defined $n; return $x->bnan() if $n <= 0 || $y->{sign} eq '-';  $x->{value} = $CALC->_lsft($x->{value},$y->{value},$n);  $x->round(@r);  }sub brsft   {  # (BINT or num_str, BINT or num_str) return BINT  # compute x >> y, base n, y >= 0    # set up parameters  my ($self,$x,$y,$n,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,$n,@r) = objectify(2,@_);    }  return $x if $x->modify('brsft');  return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);  return $x->round(@r) if $y->is_zero();  return $x->bzero(@r) if $x->is_zero();		# 0 => 0  $n = 2 if !defined $n; return $x->bnan() if $n <= 0 || $y->{sign} eq '-';   # this only works for negative numbers when shifting in base 2  if (($x->{sign} eq '-') && ($n == 2))    {    return $x->round(@r) if $x->is_one('-');	# -1 => -1    if (!$y->is_one())      {      # although this is O(N*N) in calc (as_bin!) it is O(N) in Pari et al      # but perhaps there is a better emulation for two's complement shift...      # if $y != 1, we must simulate it by doing:      # convert to bin, flip all bits, shift, and be done      $x->binc();			# -3 => -2      my $bin = $x->as_bin();      $bin =~ s/^-0b//;			# strip '-0b' prefix      $bin =~ tr/10/01/;		# flip bits      # now shift      if ($y >= CORE::length($bin))        {	$bin = '0'; 			# shifting to far right creates -1					# 0, because later increment makes 					# that 1, attached '-' makes it '-1'					# because -1 >> x == -1 !        }       else	{	$bin =~ s/.{$y}$//;		# cut off at the right side        $bin = '1' . $bin;		# extend left side by one dummy '1'        $bin =~ tr/10/01/;		# flip bits back	}      my $res = $self->new('0b'.$bin);	# add prefix and convert back      $res->binc();			# remember to increment      $x->{value} = $res->{value};	# take over value      return $x->round(@r);		# we are done now, magic, isn't?      }    # x < 0, n == 2, y == 1    $x->bdec();				# n == 2, but $y == 1: this fixes it    }  $x->{value} = $CALC->_rsft($x->{value},$y->{value},$n);  $x->round(@r);  }sub band   {  #(BINT or num_str, BINT or num_str) return BINT  # compute x & y   # 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('band');  $r[3] = $y;				# no push!  return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);  my $sx = $x->{sign} eq '+' ? 1 : -1;  my $sy = $y->{sign} eq '+' ? 1 : -1;    if ($sx == 1 && $sy == 1)    {    $x->{value} = $CALC->_and($x->{value},$y->{value});    return $x->round(@r);    }    if ($CAN{signed_and})    {    $x->{value} = $CALC->_signed_and($x->{value},$y->{value},$sx,$sy);    return $x->round(@r);    }   require $EMU_LIB;  __emu_band($self,$x,$y,$sx,$sy,@r);  }sub bior   {  #(BINT or num_str, BINT or num_str) return BINT  # compute x | y    # 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('bior');  $r[3] = $y;				# no push!  return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);  my $sx = $x->{sign} eq '+' ? 1 : -1;  my $sy = $y->{sign} eq '+' ? 1 : -1;  # the sign of X follows the sign of X, e.g. sign of Y irrelevant for bior()    # don't use lib for negative values  if ($sx == 1 && $sy == 1)    {    $x->{value} = $CALC->_or($x->{value},$y->{value});    return $x->round(@r);    }  # if lib can do negative values, let it handle this  if ($CAN{signed_or})    {    $x->{value} = $CALC->_signed_or($x->{value},$y->{value},$sx,$sy);    return $x->round(@r);    }  require $EMU_LIB;  __emu_bior($self,$x,$y,$sx,$sy,@r);  }sub bxor   {  #(BINT or num_str, BINT or num_str) return BINT  # compute x ^ y    # 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('bxor');  $r[3] = $y;				# no push!  return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);    my $sx = $x->{sign} eq '+' ? 1 : -1;  my $sy = $y->{sign} eq '+' ? 1 : -1;  # don't use lib for negative values  if ($sx == 1 && $sy == 1)    {    $x->{value} = $CALC->_xor($x->{value},$y->{value});    return $x->round(@r);    }    # if lib can do negative values, let it handle this  if ($CAN{signed_xor})    {    $x->{value} = $CALC->_signed_xor($x->{value},$y->{value},$sx,$sy);    return $x->round(@r);    }  require $EMU_LIB;  __emu_bxor($self,$x,$y,$sx,$sy,@r);  }sub length  {  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);  my $e = $CALC->_len($x->{value});   wantarray ? ($e,0) : $e;  }sub digit  {  # return the nth decimal digit, negative values count backward, 0 is right  my ($self,$x,$n) = ref($_[0]) ? (undef,@_) : objectify(1,@_);  $n = $n->numify() if ref($n);  $CALC->_digit($x->{value},$n||0);  }sub _trailing_zeros  {  # return the amount of trailing zeros in $x (as scalar)  my $x = shift;  $x = $class->new($x) unless ref $x;  return 0 if $x->{sign} !~ /^[+-]$/;	# NaN, inf, -inf etc  $CALC->_zeros($x->{value});		# must handle odd values, 0 etc  }sub bsqrt  {  # calculate square root of $x  my ($self,$x,@r) = ref($_[0]) ? (undef,@_) : objectify(1,@_);  return $x if $x->modify('bsqrt');  return $x->bnan() if $x->{sign} !~ /^\+/;	# -x or -inf or NaN => NaN  return $x if $x->{sign} eq '+inf';		# sqrt(+inf) == inf  return $upgrade->bsqrt($x,@r) if defined $upgrade;  $x->{value} = $CALC->_sqrt($x->{value});  $x->round(@r);  }sub broot  {  # calculate $y'th root of $x   # set up parameters  my ($self,$x,$y,@r) = (ref($_[0]),@_);  $y = $self->new(2) unless defined $y;  # objectify is costly, so avoid it  if ((!ref($x)) || (ref($x) ne ref($y)))    {    ($self,$x,$y,@r) = objectify(2,$self || $class,@_);    }  return $x if $x->modify('broot');  # NaN handling: $x ** 1/0, x or y NaN, or y inf/-inf or y == 0  return $x->bnan() if $x->{sign} !~ /^\+/ || $y->is_zero() ||         $y->{sign} !~ /^\+$/;  return $x->round(@r)    if $x->is_zero() || $x->is_one() || $x->is_inf() || $y->is_one();  return $upgrade->new($x)->broot($upgrade->new($y),@r) if defined $upgrade;  $x->{value} = $CALC->_root($x->{value},$y->{value});  $x->round(@r);  }sub exponent  {  # return a copy of the exponent (here always 0, NaN or 1 for $m == 0)  my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);   if ($x->{sign} !~ /^[+-]$/)    {    my $s = $x->{sign}; $s =~ s/^[+-]//;  # NaN, -inf,+inf => NaN or inf    return $self->new($s);    }  return $self->bone() if $x->is_zero();  # 12300 => 2 trailing zeros => exponent is 2  $self->new( $CALC->_zeros($x->{value}) );  }sub mantissa  {  # return the mantissa (compatible to Math::BigFloat, e.g. reduced)  my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);  if ($x->{sign} !~ /^[+-]$/)    {    # for NaN, +inf, -inf: keep the sign    return $self->new($x->{sign});    }  my $m = $x->copy(); delete $m->{_p}; delete $m->{_a};  # that's a bit inefficient:  my $zeros = $CALC->_zeros($m->{value});  $m->brsft($zeros,10) if $zeros != 0;  $m;  }sub parts  {  # return a copy of both the exponent and the mantissa  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);  ($x->mantissa(),$x->exponent());  }   ############################################################################### rounding functionssub bfround  {  # precision: round to the $Nth digit left (+$n) or right (-$n) from the '.'  # $n == 0 || $n == 1 => round to integer  my $x = shift; my $self = ref($x) || $x; $x = $self->new($x) unless ref $x;  my ($scale,$mode) = $x->_scale_p(@_);  return $x if !defined $scale || $x->modify('bfround');	# no-op  # no-op for BigInts if $n <= 0  $x->bround( $x->length()-$scale, $mode) if $scale > 0;  delete $x->{_a};	# delete to save memory  $x->{_p} = $scale;	# store new _p  $x;  }sub _scan_for_nonzero  {  # internal, used by bround() to scan for non-zeros after a '5'  my ($x,$pad,$xs,$len) = @_;   return 0 if $len == 1;		# "5" is trailed by invisible zeros  my $follow = $pad - 1;  return 0 if $follow > $len || $follow < 1;  # use the string form to check whether only '0's follow or not  substr ($xs,-$follow) =~ /[^0]/ ? 1 : 0;  }sub fround  {  # Exists to make life easier for switch between MBF and MBI (should we  # autoload fxxx() like MBF does for bxxx()?)  my $x = shift; $x = $class->new($x) unless ref $x;  $x->bround(@_);  }sub bround  {  # accuracy: +$n preserve $n digits from left,  #           -$n preserve $n digits from right (f.i. for 0.1234 style in MBF)  # no-op for $n == 0  # and overwrite the rest with 0's, return normalized number  # do not return $x->bnorm(), but $x  my $x = shift; $x = $class->new($x) unless ref $x;  my ($scale,$mode) = $x->_scale_a(@_);  return $x if !defined $scale || $x->modify('bround');	# no-op    if ($x->is_zero() || $scale == 0)    {    $x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale; # 3 > 2    return $x;    }  return $x if $x->{sign} !~ /^[+-]$/;		# inf, NaN  # we have fewer digits than we want to scale to  my $len = $x->length();  # convert $scale to a scalar in case it is an object (put's a limit on the  # number length, but this would already limited by memory constraints), makes  # it faster  $scale = $scale->numify() if ref ($scale);  # scale < 0, but > -len (not >=!)  if (($scale < 0 && $scale < -$len-1) || ($scale >= $len))    {    $x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale; # 3 > 2    return $x;     }     # count of 0's to pad, from left (+) or right (-): 9 - +6 => 3, or |-6| => 6  my

⌨️ 快捷键说明

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