1 package Math::BigInt::CalcEmu;
7 our $VERSION = '1.999707';
17 $CALC_EMU = Math::BigInt->config()->{'lib'};
18 # register us with MBI to get notified of future lib changes
19 Math::BigInt::_register_callback( __PACKAGE__, sub { $CALC_EMU = $_[0]; } );
24 my ($self,$x,$y,$sx,$sy,@r) = @_;
26 return $x->bzero(@r) if $y->is_zero() || $x->is_zero();
28 my $sign = 0; # sign of result
29 $sign = 1 if $sx == -1 && $sy == -1;
33 if ($sx == -1) # if x is negative
35 # two's complement: inc and flip all "bits" in $bx
36 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
38 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
42 $bx = $x->as_hex(); # get binary representation
44 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
46 if ($sy == -1) # if y is negative
48 # two's complement: inc and flip all "bits" in $by
49 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
51 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
55 $by = $y->as_hex(); # get binary representation
57 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
59 # now we have bit-strings from X and Y, reverse them for padding
63 # padd the shorter string
64 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
65 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
66 my $diff = CORE::length($bx) - CORE::length($by);
69 # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
74 # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
75 $bx .= $xx x abs($diff);
78 # and the strings together
81 # and reverse the result again
84 # One of $x or $y was negative, so need to flip bits in the result.
85 # In both cases (one or two of them negative, or both positive) we need
86 # to get the characters back.
89 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
93 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
96 # leading zeros will be stripped by _from_hex()
98 $x->{value} = $CALC_EMU->_from_hex( $bx );
100 # calculate sign of result
102 $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
104 $x->bdec() if $sign == 1;
111 my ($self,$x,$y,$sx,$sy,@r) = @_;
113 return $x->round(@r) if $y->is_zero();
115 my $sign = 0; # sign of result
116 $sign = 1 if ($sx == -1) || ($sy == -1);
120 if ($sx == -1) # if x is negative
122 # two's complement: inc and flip all "bits" in $bx
123 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
125 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
129 $bx = $x->as_hex(); # get binary representation
131 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
133 if ($sy == -1) # if y is negative
135 # two's complement: inc and flip all "bits" in $by
136 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
138 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
142 $by = $y->as_hex(); # get binary representation
144 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
146 # now we have bit-strings from X and Y, reverse them for padding
150 # padd the shorter string
151 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
152 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
153 my $diff = CORE::length($bx) - CORE::length($by);
160 $bx .= $xx x abs($diff);
163 # or the strings together
166 # and reverse the result again
169 # one of $x or $y was negative, so need to flip bits in the result
170 # in both cases (one or two of them negative, or both positive) we need
171 # to get the characters back.
174 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
178 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
181 # leading zeros will be stripped by _from_hex()
183 $x->{value} = $CALC_EMU->_from_hex( $bx );
185 # calculate sign of result
187 $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
189 # if one of X or Y was negative, we need to decrement result
190 $x->bdec() if $sign == 1;
197 my ($self,$x,$y,$sx,$sy,@r) = @_;
199 return $x->round(@r) if $y->is_zero();
201 my $sign = 0; # sign of result
202 $sign = 1 if $x->{sign} ne $y->{sign};
206 if ($sx == -1) # if x is negative
208 # two's complement: inc and flip all "bits" in $bx
209 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
211 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
215 $bx = $x->as_hex(); # get binary representation
217 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
219 if ($sy == -1) # if y is negative
221 # two's complement: inc and flip all "bits" in $by
222 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
224 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
228 $by = $y->as_hex(); # get binary representation
230 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
232 # now we have bit-strings from X and Y, reverse them for padding
236 # padd the shorter string
237 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
238 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
239 my $diff = CORE::length($bx) - CORE::length($by);
246 $bx .= $xx x abs($diff);
249 # xor the strings together
252 # and reverse the result again
255 # one of $x or $y was negative, so need to flip bits in the result
256 # in both cases (one or two of them negative, or both positive) we need
257 # to get the characters back.
260 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
264 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
267 # leading zeros will be stripped by _from_hex()
269 $x->{value} = $CALC_EMU->_from_hex( $bx );
271 # calculate sign of result
273 $x->{sign} = '-' if $sx != $sy && !$x->is_zero();
275 $x->bdec() if $sign == 1;
280 ##############################################################################
281 ##############################################################################
291 Math::BigInt::CalcEmu - Emulate low-level math with BigInt code
295 use Math::BigInt::CalcEmu;
299 Contains routines that emulate low-level math functions in BigInt, e.g.
300 optional routines the low-level math package does not provide on its own.
302 Will be loaded on demand and called automatically by BigInt.
304 Stuff here is really low-priority to optimize, since it is far better to
305 implement the operation in the low-level math library directly, possible even
306 using a call to the native lib.
322 Please report any bugs or feature requests to
323 C<bug-math-bigint at rt.cpan.org>, or through the web interface at
324 L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt>
326 We will be notified, and then you'll automatically be notified of progress on
327 your bug as I make changes.
331 You can find documentation for this module with the perldoc command.
333 perldoc Math::BigInt::CalcEmu
335 You can also look for information at:
339 =item * RT: CPAN's request tracker
341 L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigInt>
343 =item * AnnoCPAN: Annotated CPAN documentation
345 L<http://annocpan.org/dist/Math-BigInt>
349 L<http://cpanratings.perl.org/dist/Math-BigInt>
353 L<http://search.cpan.org/dist/Math-BigInt/>
355 =item * CPAN Testers Matrix
357 L<http://matrix.cpantesters.org/?dist=Math-BigInt>
359 =item * The Bignum mailing list
363 =item * Post to mailing list
365 C<bignum at lists.scsys.co.uk>
367 =item * View mailing list
369 L<http://lists.scsys.co.uk/pipermail/bignum/>
371 =item * Subscribe/Unsubscribe
373 L<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/bignum>
381 This program is free software; you may redistribute it and/or modify it under
382 the same terms as Perl itself.
386 (c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by
391 L<Math::BigInt>, L<Math::BigFloat>,
392 L<Math::BigInt::GMP> and L<Math::BigInt::Pari>.