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

📄 calc.pm

📁 网页留言本,比一般的留言簿管用
💻 PM
📖 第 1 页 / 共 4 页
字号:
  my $mask = $AND_MASK;  my $x1 = $x;  my $y1 = _copy($c,$y);			# make copy  $x = _zero();  my ($b,$xrr,$yrr);  use integer;  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))    {    ($x1, $xr) = _div($c,$x1,$mask);    ($y1, $yr) = _div($c,$y1,$mask);    # make ints() from $xr, $yr    # this is when the AND_BITS are greater tahn $BASE and is slower for    # small (<256 bits) numbers, but faster for large numbers. Disabled    # due to KISS principle#    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }#    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }#    _add($c,$x, _mul($c, _new( $c, \($xrr & $yrr) ), $m) );        # 0+ due to '&' doesn't work in strings    _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) );    _mul($c,$m,$mask);    }  $x;  }sub _xor  {  my ($c,$x,$y) = @_;  return _zero() if _acmp($c,$x,$y) == 0;	# shortcut (see -and)  my $m = _one(); my ($xr,$yr);  my $mask = $XOR_MASK;  my $x1 = $x;  my $y1 = _copy($c,$y);			# make copy  $x = _zero();  my ($b,$xrr,$yrr);  use integer;  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))    {    ($x1, $xr) = _div($c,$x1,$mask);    ($y1, $yr) = _div($c,$y1,$mask);    # make ints() from $xr, $yr (see _and())    #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }    #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }    #_add($c,$x, _mul($c, _new( $c, \($xrr ^ $yrr) ), $m) );    # 0+ due to '^' doesn't work in strings    _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) );    _mul($c,$m,$mask);    }  # the loop stops when the shorter of the two numbers is exhausted  # the remainder of the longer one will survive bit-by-bit, so we simple  # multiply-add it in  _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);  _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);    $x;  }sub _or  {  my ($c,$x,$y) = @_;  return $x if _acmp($c,$x,$y) == 0;		# shortcut (see _and)  my $m = _one(); my ($xr,$yr);  my $mask = $OR_MASK;  my $x1 = $x;  my $y1 = _copy($c,$y);			# make copy  $x = _zero();  my ($b,$xrr,$yrr);  use integer;  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))    {    ($x1, $xr) = _div($c,$x1,$mask);    ($y1, $yr) = _div($c,$y1,$mask);    # make ints() from $xr, $yr (see _and())#    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }#    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }#    _add($c,$x, _mul($c, _new( $c, \($xrr | $yrr) ), $m) );        # 0+ due to '|' doesn't work in strings    _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) );    _mul($c,$m,$mask);    }  # the loop stops when the shorter of the two numbers is exhausted  # the remainder of the longer one will survive bit-by-bit, so we simple  # multiply-add it in  _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);  _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);    $x;  }sub _as_hex  {  # convert a decimal number to hex (ref to array, return ref to string)  my ($c,$x) = @_;  my $x1 = _copy($c,$x);  my $es = '';  my ($xr, $h, $x10000);  if ($] >= 5.006)    {    $x10000 = [ 0x10000 ]; $h = 'h4';    }  else    {    $x10000 = [ 0x1000 ]; $h = 'h3';    }  while (! _is_zero($c,$x1))    {    ($x1, $xr) = _div($c,$x1,$x10000);    $es .= unpack($h,pack('v',$xr->[0]));    }  $es = reverse $es;  $es =~ s/^[0]+//;   # strip leading zeros  $es = '0x' . $es;  \$es;  }sub _as_bin  {  # convert a decimal number to bin (ref to array, return ref to string)  my ($c,$x) = @_;  my $x1 = _copy($c,$x);  my $es = '';  my ($xr, $b, $x10000);  if ($] >= 5.006)    {    $x10000 = [ 0x10000 ]; $b = 'b16';    }  else    {    $x10000 = [ 0x1000 ]; $b = 'b12';    }  while (! _is_zero($c,$x1))    {    ($x1, $xr) = _div($c,$x1,$x10000);    $es .= unpack($b,pack('v',$xr->[0]));    }  $es = reverse $es;  $es =~ s/^[0]+//;   # strip leading zeros  $es = '0b' . $es;  \$es;  }sub _from_hex  {  # convert a hex number to decimal (ref to string, return ref to array)  my ($c,$hs) = @_;  my $mul = _one();  my $m = [ 0x10000 ];				# 16 bit at a time  my $x = _zero();  my $len = length($$hs)-2;  $len = int($len/4);				# 4-digit parts, w/o '0x'  my $val; my $i = -4;  while ($len >= 0)    {    $val = substr($$hs,$i,4);    $val =~ s/^[+-]?0x// if $len == 0;		# for last part only because    $val = hex($val);				# hex does not like wrong chars    $i -= 4; $len --;    _add ($c, $x, _mul ($c, [ $val ], $mul ) ) if $val != 0;    _mul ($c, $mul, $m ) if $len >= 0; 		# skip last mul    }  $x;  }sub _from_bin  {  # convert a hex number to decimal (ref to string, return ref to array)  my ($c,$bs) = @_;  # instead of converting 8 bit at a time, it is faster to convert the  # number to hex, and then call _from_hex.  my $hs = $$bs;  $hs =~ s/^[+-]?0b//;					# remove sign and 0b  my $l = length($hs);					# bits  $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0;	# padd left side w/ 0  my $h = unpack('H*', pack ('B*', $hs));		# repack as hex  return $c->_from_hex(\('0x'.$h));   my $mul = _one();  my $m = [ 0x100 ];				# 8 bit at a time  my $x = _zero();  my $len = length($$bs)-2;  $len = int($len/8);				# 4-digit parts, w/o '0x'  my $val; my $i = -8;  while ($len >= 0)    {    $val = substr($$bs,$i,8);    $val =~ s/^[+-]?0b// if $len == 0;		# for last part only    $val = ord(pack('B8',substr('00000000'.$val,-8,8)));     $i -= 8; $len --;    _add ($c, $x, _mul ($c, [ $val ], $mul ) ) if $val != 0;    _mul ($c, $mul, $m ) if $len >= 0; 		# skip last mul    }  $x;  }############################################################################### special modulus functionssub _modinv  {  # modular inverse  my ($c,$x,$y) = @_;  my $u = _zero($c); my $u1 = _one($c);  my $a = _copy($c,$y); my $b = _copy($c,$x);  # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the  # result ($u) at the same time. See comments in BigInt for why this works.  my $q;  ($a, $q, $b) = ($b, _div($c,$a,$b));		# step 1  my $sign = 1;  while (!_is_zero($c,$b))    {    my $t = _add($c, 				# step 2:       _mul($c,_copy($c,$u1), $q) ,		#  t =  u1 * q       $u );					#     + u    $u = $u1;					#  u = u1, u1 = t    $u1 = $t;    $sign = -$sign;    ($a, $q, $b) = ($b, _div($c,$a,$b));	# step 1    }  # if the gcd is not 1, then return NaN  return (undef,undef) unless _is_one($c,$a);   $sign = $sign == 1 ? '+' : '-';  ($u1,$sign);  }sub _modpow  {  # modulus of power ($x ** $y) % $z  my ($c,$num,$exp,$mod) = @_;  # in the trivial case,  if (_is_one($c,$mod))    {    splice @$num,0,1; $num->[0] = 0;    return $num;    }  if ((scalar @$num == 1) && (($num->[0] == 0) || ($num->[0] == 1)))    {    $num->[0] = 1;    return $num;    }#  $num = _mod($c,$num,$mod);	# this does not make it faster  my $acc = _copy($c,$num); my $t = _one();  my $expbin = ${_as_bin($c,$exp)}; $expbin =~ s/^0b//;  my $len = length($expbin);  while (--$len >= 0)    {    if ( substr($expbin,$len,1) eq '1')			# is_odd      {      _mul($c,$t,$acc);      $t = _mod($c,$t,$mod);      }    _mul($c,$acc,$acc);    $acc = _mod($c,$acc,$mod);    }  @$num = @$t;  $num;  }############################################################################################################################################################1;__END__=head1 NAMEMath::BigInt::Calc - Pure Perl module to support Math::BigInt=head1 SYNOPSISProvides support for big integer calculations. Not intended to be used by othermodules (except Math::BigInt::Cached). Other modules which sport the samefunctions can also be used to support Math::Bigint, like Math::BigInt::Pari.=head1 DESCRIPTIONIn order to allow for multiple big integer libraries, Math::BigInt wasrewritten to use library modules for core math routines. Any module whichfollows the same API as this can be used instead by using the following:	use Math::BigInt lib => 'libname';'libname' is either the long name ('Math::BigInt::Pari'), or only the shortversion like 'Pari'.=head1 EXPORTThe following functions MUST be defined in order to support the use byMath::BigInt:	_new(string)	return ref to new object from ref to decimal string	_zero()		return a new object with value 0	_one()		return a new object with value 1	_str(obj)	return ref to a string representing the object	_num(obj)	returns a Perl integer/floating point number			NOTE: because of Perl numeric notation defaults,			the _num'ified obj may lose accuracy due to 			machine-dependend floating point size limitations                    	_add(obj,obj)	Simple addition of two objects	_mul(obj,obj)	Multiplication of two objects	_div(obj,obj)	Division of the 1st object by the 2nd			In list context, returns (result,remainder).			NOTE: this is integer math, so no			fractional part will be returned.	_sub(obj,obj)	Simple subtraction of 1 object from another			a third, optional parameter indicates that the params			are swapped. In this case, the first param needs to			be preserved, while you can destroy the second.			sub (x,y,1) => return x - y and keep x intact!	_dec(obj)	decrement object by one (input is garant. to be > 0)	_inc(obj)	increment object by one	_acmp(obj,obj)	<=> operator for objects (return -1, 0 or 1)	_len(obj)	returns count of the decimal digits of the object	_digit(obj,n)	returns the n'th decimal digit of object	_is_one(obj)	return true if argument is +1	_is_zero(obj)	return true if argument is 0	_is_even(obj)	return true if argument is even (0,2,4,6..)	_is_odd(obj)	return true if argument is odd (1,3,5,7..)	_copy		return a ref to a true copy of the object	_check(obj)	check whether internal representation is still intact			return 0 for ok, otherwise error message as stringThe following functions are optional, and can be defined if the underlying libhas a fast way to do them. If undefined, Math::BigInt will use pure Perl (henceslow) fallback routines to emulate these:	_from_hex(str)	return ref to new object from ref to hexadecimal string	_from_bin(str)	return ref to new object from ref to binary string		_as_hex(str)	return ref to scalar string containing the value as			unsigned hex string, with the '0x' prepended.			Leading zeros must be stripped.	_as_bin(str)	Like as_hex, only as binary string containing only			zeros and ones. Leading zeros must be stripped and a			'0b' must be prepended.		_rsft(obj,N,B)	shift object in base B by N 'digits' right			For unsupported bases B, return undef to signal failure	_lsft(obj,N,B)	shift object in base B by N 'digits' left			For unsupported bases B, return undef to signal failure		_xor(obj1,obj2)	XOR (bit-wise) object 1 with object 2			Note: XOR, AND and OR pad with zeros if size mismatches	_and(obj1,obj2)	AND (bit-wise) object 1 with object 2	_or(obj1,obj2)	OR (bit-wise) object 1 with object 2	_mod(obj,obj)	Return remainder of div of the 1st by the 2nd object	_sqrt(obj)	return the square root of object (truncate to int)	_fac(obj)	return factorial of object 1 (1*2*3*4..)	_pow(obj,obj)	return object 1 to the power of object 2	_gcd(obj,obj)	return Greatest Common Divisor of two objects		_zeros(obj)	return number of trailing decimal zeros	_modinv		return inverse modulus	_modpow		return modulus of power ($x ** $y) % $zInput strings come in as unsigned but with prefix (i.e. as '123', '0xabc'or '0b1101').Testing of input parameter validity is done by the caller, so you need notworry about underflow (f.i. in C<_sub()>, C<_dec()>) nor about division byzero or similar cases.The first parameter can be modified, that includes the possibility that youreturn a reference to a completely different object instead. Although keepingthe reference and just changing it's contents is prefered over creating andreturning a different reference.Return values are always references to objects or strings. Exceptions areC<_lsft()> and C<_rsft()>, which return undef if they can not shift theargument. This is used to delegate shifting of bases different than the oneyou can support back to Math::BigInt, which will use some generic code tocalculate the result.=head1 WRAP YOUR OWNIf you want to port your own favourite c-lib for big numbers to theMath::BigInt interface, you can take any of the already existing modules asa rough guideline. You should really wrap up the latest BigInt and BigFloattestsuites with your module, and replace in them any of the following:	use Math::BigInt;by this:	use Math::BigInt lib => 'yourlib';This way you ensure that your library really works 100% within Math::BigInt.=head1 LICENSE This program is free software; you may redistribute it and/or modify it underthe same terms as Perl itself. =head1 AUTHORSOriginal math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>in late 2000, 2001.Seperated from BigInt and shaped API with the help of John Peacock.=head1 SEE ALSOL<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,L<Math::BigInt::GMP>, L<Math::BigInt::Cached> and L<Math::BigInt::Pari>.=cut

⌨️ 快捷键说明

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