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

📄 bigint.pm

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 PM
📖 第 1 页 / 共 5 页
字号:
  while (@_)    {    $y = shift; $y = $self->new($y) if !ref($y);    return $x->bnan() if $y->{sign} !~ /^[+-]$/;	# y NaN?    $x->{value} = $CALC->_gcd($x->{value},$y->{value});    last if $CALC->_is_one($x->{value});    }  $x;  }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->binc()->bneg();			# binc already does round  }############################################################################### is_foo test routines# we don't need $self, so undef instead of ref($_[0]) make it slightly fastersub is_zero  {  # return true if arg (BINT or num_str) is zero (array '+', '0')  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]) ? (undef,$_[0]) : objectify(1,@_);  $x->{sign} eq $nan ? 1 : 0;  }sub is_inf  {  # return true if arg (BINT or num_str) is +-inf  my ($self,$x,$sign) = ref($_[0]) ? (undef,@_) : objectify(1,@_);  if (defined $sign)    {    $sign = '[+-]inf' if $sign eq '';	# +- doesn't matter, only that's inf    $sign = "[$1]inf" if $sign =~ /^([+-])(inf)?$/;	# extract '+' or '-'    return $x->{sign} =~ /^$sign$/ ? 1 : 0;    }  $x->{sign} =~ /^[+-]inf$/ ? 1 : 0;		# only +-inf is infinity  }sub is_one  {  # return true if arg (BINT or num_str) is +1, or -1 if sign is given  my ($self,$x,$sign) = ref($_[0]) ? (undef,@_) : objectify(1,@_);      $sign = '+' if !defined $sign || $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  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  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)  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);  return 1 if $x->{sign} eq '+inf';			# +inf is positive   # 0+ is neither positive nor negative  ($x->{sign} eq '+' && !$x->is_zero()) ? 1 : 0;	  }sub is_negative  {  # return true when arg (BINT or num_str) is negative (< 0)  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);    $x->{sign} =~ /^-/ ? 1 : 0; 		# -inf is negative, but NaN is not  }sub is_int  {  # return true when arg (BINT or num_str) is an integer  # always true for BigInt, but different for BigFloats  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);    $x->{sign} =~ /^[+-]$/ ? 1 : 0;		# inf/-inf/NaN aren't  }###############################################################################sub bmul   {   # multiply the first number by the second number  # (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,$upgrade->new($y),@r)   if defined $upgrade && !$y->isa($self);    $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);  }sub bmuladd  {   # multiply two numbers and then add the third to the result  # (BINT or num_str, BINT or num_str, BINT or num_str) return BINT  # set up parameters  my ($self,$x,$y,$z,@r) = (ref($_[0]),@_);  # objectify is costly, so avoid it  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))    {    ($self,$x,$y,$z,@r) = objectify(3,@_);    }  return $x if $x->modify('bmuladd');  return $x->bnan() if  ($x->{sign} eq $nan) ||			($y->{sign} eq $nan) ||			($z->{sign} eq $nan);  # inf handling of x and y  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('-');    }  # inf handling x*y and z  if (($z->{sign} =~ /^[+-]inf$/))    {    # something +-inf => +-inf    $x->{sign} = $z->{sign}, return $x if $z->{sign} =~ /^[+-]inf$/;    }  return $upgrade->bmuladd($x,$upgrade->new($y),$upgrade->new($z),@r)   if defined $upgrade && (!$y->isa($self) || !$z->isa($self) || !$x->isa($self));   # TODO: what if $y and $z have A or P set?  $r[3] = $z;				# 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  my ($sx, $sz) = ( $x->{sign}, $z->{sign} ); 		# get signs  if ($sx eq $sz)      {    $x->{value} = $CALC->_add($x->{value},$z->{value});	# same sign, abs add    }  else     {    my $a = $CALC->_acmp ($z->{value},$x->{value});	# absolute compare    if ($a > 0)                                 {      $x->{value} = $CALC->_sub($z->{value},$x->{value},1); # abs sub w/ swap      $x->{sign} = $sz;      }     elsif ($a == 0)      {      # speedup, if equal, set result to 0      $x->{value} = $CALC->_zero();      $x->{sign} = '+';      }    else # a < 0      {      $x->{value} = $CALC->_sub($x->{value}, $z->{value}); # abs sub      }    }  $x->round(@r);  }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),$upgrade->new($y),@r)   if defined $upgrade;     $r[3] = $y;					# no push!  # calc new sign and in case $y == +/- 1, return $x  my $xsign = $x->{sign};				# keep  $x->{sign} = ($x->{sign} ne $y->{sign} ? '-' : '+');   if (wantarray)    {    my $rem = $self->bzero();     ($x->{value},$rem->{value}) = $CALC->_div($x->{value},$y->{value});    $x->{sign} = '+' if $CALC->_is_zero($x->{value});    $rem->{_a} = $x->{_a};    $rem->{_p} = $x->{_p};    $x->round(@r);    if (! $CALC->_is_zero($rem->{value}))      {      $rem->{sign} = $y->{sign};      $rem = $y->copy()->bsub($rem) if $xsign ne $y->{sign}; # one of them '-'      }    else      {      $rem->{sign} = '+';			# dont leave -0      }    $rem->round(@r);    return ($x,$rem);    }  $x->{value} = $CALC->_div($x->{value},$y->{value});  $x->{sign} = '+' if $CALC->_is_zero($x->{value});  $x->round(@r);  }################################################################################ modulus functionssub bmod   {  # modulus (or remainder)  # (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('bmod');  $r[3] = $y;					# no push!  if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero())    {    my ($d,$r) = $self->_div_inf($x,$y);    $x->{sign} = $r->{sign};    $x->{value} = $r->{value};    return $x->round(@r);    }  # calc new sign and in case $y == +/- 1, return $x  $x->{value} = $CALC->_mod($x->{value},$y->{value});  if (!$CALC->_is_zero($x->{value}))    {    $x->{value} = $CALC->_sub($y->{value},$x->{value},1) 	# $y-$x      if ($x->{sign} ne $y->{sign});    $x->{sign} = $y->{sign};    }   else    {    $x->{sign} = '+';				# dont leave -0    }  $x->round(@r);  }sub bmodinv  {  # Modular inverse.  given a number which is (hopefully) relatively  # prime to the modulus, calculate its inverse using Euclid's  # alogrithm.  If the number is not relatively prime to the modulus  # (i.e. their gcd is not one) then NaN is returned.  # set up parameters  my ($self,$x,$y,@r) = (undef,@_);  # 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('bmodinv');  return $x->bnan()        if ($y->{sign} ne '+'                           # -, NaN, +inf, -inf         || $x->is_zero()                               # or num == 0         || $x->{sign} !~ /^[+-]$/                      # or num NaN, inf, -inf        );  # put least residue into $x if $x was negative, and thus make it positive  $x->bmod($y) if $x->{sign} eq '-';  my $sign;  ($x->{value},$sign) = $CALC->_modinv($x->{value},$y->{value});  return $x->bnan() if !defined $x->{value};		# in case no GCD found  return $x if !defined $sign;			# already real result  $x->{sign} = $sign;				# flip/flop see below  $x->bmod($y);					# calc real result  $x;  }sub bmodpow  {  # takes a very large number to a very large exponent in a given very  # large modulus, quickly, thanks to binary exponentation. Supports  # negative exponents.  my ($self,$num,$exp,$mod,@r) = objectify(3,@_);  return $num if $num->modify('bmodpow');  # check modulus for valid values  return $num->bnan() if ($mod->{sign} ne '+'		# NaN, - , -inf, +inf                       || $mod->is_zero());  # check exponent for valid values  if ($exp->{sign} =~ /\w/)     {    # i.e., if it's NaN, +inf, or -inf...    return $num->bnan();    }  $num->bmodinv ($mod) if ($exp->{sign} eq '-');  # check num for valid values (also NaN if there was no inverse but $exp < 0)  return $num->bnan() if $num->{sign} !~ /^[+-]$/;  # $mod is positive, sign on $exp is ignored, result also positive  $num->{value} = $CALC->_modpow($num->{value},$exp->{value},$mod->{value});  $num;  }###############################################################################sub bfac  {  # (BINT or num_str, BINT or num_str) return BINT  # compute factorial number from $x, modify $x in place  my ($self,$x,@r) = ref($_[0]) ? (undef,@_) : objectify(1,@_);  return $x if $x->modify('bfac') || $x->{sign} eq '+inf';	# inf => inf  return $x->bnan() if $x->{sign} ne '+';			# NaN, <0 etc => NaN  $x->{value} = $CALC->_fac($x->{value});  $x->round(@r);  } sub bpow   {  # (BINT or num_str, BINT or num_str) return BINT  # compute power of two numbers -- stolen from Knuth Vol 2 pg 233  # modifies first argument  # 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('bpow');  return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;

⌨️ 快捷键说明

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