1 package Math
::BigInt
::CalcEmu
;
5 # use warnings; # dont use warnings for older Perls
18 $CALC_EMU = Math
::BigInt
->config()->{'lib'};
19 # register us with MBI to get notified of future lib changes
20 Math
::BigInt
::_register_callback
( __PACKAGE__
, sub { $CALC_EMU = $_[0]; } );
25 my ($self,$x,$y,$sx,$sy,@r) = @_;
27 return $x->bzero(@r) if $y->is_zero() || $x->is_zero();
29 my $sign = 0; # sign of result
30 $sign = 1 if $sx == -1 && $sy == -1;
34 if ($sx == -1) # if x is negative
36 # two's complement: inc and flip all "bits" in $bx
37 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
39 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
43 $bx = $x->as_hex(); # get binary representation
45 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
47 if ($sy == -1) # if y is negative
49 # two's complement: inc and flip all "bits" in $by
50 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
52 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
56 $by = $y->as_hex(); # get binary representation
58 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
60 # now we have bit-strings from X and Y, reverse them for padding
64 # padd the shorter string
65 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
66 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
67 my $diff = CORE
::length($bx) - CORE
::length($by);
70 # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
75 # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
76 $bx .= $xx x
abs($diff);
79 # and the strings together
82 # and reverse the result again
85 # One of $x or $y was negative, so need to flip bits in the result.
86 # In both cases (one or two of them negative, or both positive) we need
87 # to get the characters back.
90 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
94 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
97 # leading zeros will be stripped by _from_hex()
99 $x->{value
} = $CALC_EMU->_from_hex( $bx );
101 # calculate sign of result
103 $x->{sign
} = '-' if $sign == 1 && !$x->is_zero();
105 $x->bdec() if $sign == 1;
112 my ($self,$x,$y,$sx,$sy,@r) = @_;
114 return $x->round(@r) if $y->is_zero();
116 my $sign = 0; # sign of result
117 $sign = 1 if ($sx == -1) || ($sy == -1);
121 if ($sx == -1) # if x is negative
123 # two's complement: inc and flip all "bits" in $bx
124 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
126 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
130 $bx = $x->as_hex(); # get binary representation
132 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
134 if ($sy == -1) # if y is negative
136 # two's complement: inc and flip all "bits" in $by
137 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
139 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
143 $by = $y->as_hex(); # get binary representation
145 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
147 # now we have bit-strings from X and Y, reverse them for padding
151 # padd the shorter string
152 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
153 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
154 my $diff = CORE
::length($bx) - CORE
::length($by);
161 $bx .= $xx x
abs($diff);
164 # or the strings together
167 # and reverse the result again
170 # one of $x or $y was negative, so need to flip bits in the result
171 # in both cases (one or two of them negative, or both positive) we need
172 # to get the characters back.
175 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
179 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
182 # leading zeros will be stripped by _from_hex()
184 $x->{value
} = $CALC_EMU->_from_hex( $bx );
186 # calculate sign of result
188 $x->{sign
} = '-' if $sign == 1 && !$x->is_zero();
190 # if one of X or Y was negative, we need to decrement result
191 $x->bdec() if $sign == 1;
198 my ($self,$x,$y,$sx,$sy,@r) = @_;
200 return $x->round(@r) if $y->is_zero();
202 my $sign = 0; # sign of result
203 $sign = 1 if $x->{sign
} ne $y->{sign
};
207 if ($sx == -1) # if x is negative
209 # two's complement: inc and flip all "bits" in $bx
210 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
212 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
216 $bx = $x->as_hex(); # get binary representation
218 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
220 if ($sy == -1) # if y is negative
222 # two's complement: inc and flip all "bits" in $by
223 $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
225 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
229 $by = $y->as_hex(); # get binary representation
231 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
233 # now we have bit-strings from X and Y, reverse them for padding
237 # padd the shorter string
238 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
239 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
240 my $diff = CORE
::length($bx) - CORE
::length($by);
247 $bx .= $xx x
abs($diff);
250 # xor the strings together
253 # and reverse the result again
256 # one of $x or $y was negative, so need to flip bits in the result
257 # in both cases (one or two of them negative, or both positive) we need
258 # to get the characters back.
261 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
265 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
268 # leading zeros will be stripped by _from_hex()
270 $x->{value
} = $CALC_EMU->_from_hex( $bx );
272 # calculate sign of result
274 $x->{sign
} = '-' if $sx != $sy && !$x->is_zero();
276 $x->bdec() if $sign == 1;
281 ##############################################################################
282 ##############################################################################
289 Math::BigInt::CalcEmu - Emulate low-level math with BigInt code
293 use Math::BigInt::CalcEmu;
297 Contains routines that emulate low-level math functions in BigInt, e.g.
298 optional routines the low-level math package does not provide on it's own.
300 Will be loaded on demand and called automatically by BigInt.
302 Stuff here is really low-priority to optimize, since it is far better to
303 implement the operation in the low-level math libary directly, possible even
304 using a call to the native lib.
316 This program is free software; you may redistribute it and/or modify it under
317 the same terms as Perl itself.
321 (c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by
326 L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
327 L<Math::BigInt::GMP> and L<Math::BigInt::Pari>.