1 package Math::BigInt::CalcEmu;
5 # use warnings; # dont use warnings for older Perls
18 $CALC_EMU = Math::BigInt->config()->{'lib'};
23 my ($self,$x,$y,$sx,$sy,@r) = @_;
25 return $x->bzero(@r) if $y->is_zero() || $x->is_zero();
27 my $sign = 0; # sign of result
28 $sign = 1 if $sx == -1 && $sy == -1;
32 if ($sx == -1) # if x is negative
34 # two's complement: inc and flip all "bits" in $bx
35 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
37 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
41 $bx = $x->as_hex(); # get binary representation
43 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
45 if ($sy == -1) # if y is negative
47 # two's complement: inc and flip all "bits" in $by
48 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
50 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
54 $by = $y->as_hex(); # get binary representation
56 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
58 # now we have bit-strings from X and Y, reverse them for padding
62 # padd the shorter string
63 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
64 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
65 my $diff = CORE::length($bx) - CORE::length($by);
68 # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
73 # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
74 $bx .= $xx x abs($diff);
77 # and the strings together
80 # and reverse the result again
83 # One of $x or $y was negative, so need to flip bits in the result.
84 # In both cases (one or two of them negative, or both positive) we need
85 # to get the characters back.
88 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
92 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
95 # leading zeros will be stripped by _from_hex()
97 $x->{value} = $CALC_EMU->_from_hex( $bx );
99 # calculate sign of result
101 $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
103 $x->bdec() if $sign == 1;
110 my ($self,$x,$y,$sx,$sy,@r) = @_;
112 return $x->round(@r) if $y->is_zero();
114 my $sign = 0; # sign of result
115 $sign = 1 if ($sx == -1) || ($sy == -1);
119 if ($sx == -1) # if x is negative
121 # two's complement: inc and flip all "bits" in $bx
122 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
124 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
128 $bx = $x->as_hex(); # get binary representation
130 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
132 if ($sy == -1) # if y is negative
134 # two's complement: inc and flip all "bits" in $by
135 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
137 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
141 $by = $y->as_hex(); # get binary representation
143 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
145 # now we have bit-strings from X and Y, reverse them for padding
149 # padd the shorter string
150 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
151 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
152 my $diff = CORE::length($bx) - CORE::length($by);
159 $bx .= $xx x abs($diff);
162 # or the strings together
165 # and reverse the result again
168 # one of $x or $y was negative, so need to flip bits in the result
169 # in both cases (one or two of them negative, or both positive) we need
170 # to get the characters back.
173 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
177 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
180 # leading zeros will be stripped by _from_hex()
182 $x->{value} = $CALC_EMU->_from_hex( $bx );
184 # calculate sign of result
186 $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
188 # if one of X or Y was negative, we need to decrement result
189 $x->bdec() if $sign == 1;
196 my ($self,$x,$y,$sx,$sy,@r) = @_;
198 return $x->round(@r) if $y->is_zero();
200 my $sign = 0; # sign of result
201 $sign = 1 if $x->{sign} ne $y->{sign};
205 if ($sx == -1) # if x is negative
207 # two's complement: inc and flip all "bits" in $bx
208 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
210 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
214 $bx = $x->as_hex(); # get binary representation
216 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
218 if ($sy == -1) # if y is negative
220 # two's complement: inc and flip all "bits" in $by
221 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
223 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
227 $by = $y->as_hex(); # get binary representation
229 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
231 # now we have bit-strings from X and Y, reverse them for padding
235 # padd the shorter string
236 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
237 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
238 my $diff = CORE::length($bx) - CORE::length($by);
245 $bx .= $xx x abs($diff);
248 # xor the strings together
251 # and reverse the result again
254 # one of $x or $y was negative, so need to flip bits in the result
255 # in both cases (one or two of them negative, or both positive) we need
256 # to get the characters back.
259 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
263 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
266 # leading zeros will be stripped by _from_hex()
268 $x->{value} = $CALC_EMU->_from_hex( $bx );
270 # calculate sign of result
272 $x->{sign} = '-' if $sx != $sy && !$x->is_zero();
274 $x->bdec() if $sign == 1;
279 ##############################################################################
280 ##############################################################################
287 Math::BigInt::CalcEmu - Emulate low-level math with BigInt code
291 Contains routines that emulate low-level math functions in BigInt, e.g.
292 optional routines the low-level math package does not provide on it's own.
294 Will be loaded on demand and automatically by BigInt.
296 Stuff here is really low-priority to optimize,
297 since it is far better to implement the operation in the low-level math
298 libary directly, possible even using a call to the native lib.
306 This program is free software; you may redistribute it and/or modify it under
307 the same terms as Perl itself.
311 (c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by
316 L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
317 L<Math::BigInt::GMP> and L<Math::BigInt::Pari>.