Include variable names in "Use of uninitialized value" warnings
[p5sagit/p5-mst-13.2.git] / lib / Math / BigInt / CalcEmu.pm
CommitLineData
ef9466ea 1package Math::BigInt::CalcEmu;
b282a552 2
3use 5.005;
4use strict;
5# use warnings; # dont use warnings for older Perls
b282a552 6use vars qw/$VERSION/;
7
9b924220 8$VERSION = '0.04';
ef9466ea 9
10package Math::BigInt;
b282a552 11
12# See SYNOPSIS below.
13
14my $CALC_EMU;
15
16BEGIN
17 {
18 $CALC_EMU = Math::BigInt->config()->{'lib'};
19 }
20
b282a552 21sub __emu_band
22 {
23 my ($self,$x,$y,$sx,$sy,@r) = @_;
24
25 return $x->bzero(@r) if $y->is_zero() || $x->is_zero();
26
27 my $sign = 0; # sign of result
28 $sign = 1 if $sx == -1 && $sy == -1;
29
30 my ($bx,$by);
31
32 if ($sx == -1) # if x is negative
33 {
34 # two's complement: inc and flip all "bits" in $bx
35 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
36 $bx =~ s/-?0x//;
37 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
38 }
39 else
40 {
41 $bx = $x->as_hex(); # get binary representation
42 $bx =~ s/-?0x//;
43 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
44 }
45 if ($sy == -1) # if y is negative
46 {
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
49 $by =~ s/-?0x//;
50 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
51 }
52 else
53 {
54 $by = $y->as_hex(); # get binary representation
55 $by =~ s/-?0x//;
56 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
57 }
58 # now we have bit-strings from X and Y, reverse them for padding
59 $bx = reverse $bx;
60 $by = reverse $by;
61
9b924220 62 # padd the shorter string
63 my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
64 my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
b282a552 65 my $diff = CORE::length($bx) - CORE::length($by);
66 if ($diff > 0)
67 {
9b924220 68 # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
69 $by .= $yy x $diff;
b282a552 70 }
71 elsif ($diff < 0)
72 {
9b924220 73 # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
74 $bx .= $xx x abs($diff);
b282a552 75 }
9b924220 76
b282a552 77 # and the strings together
78 my $r = $bx & $by;
79
80 # and reverse the result again
81 $bx = reverse $r;
82
9b924220 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
b282a552 85 # to get the characters back.
86 if ($sign == 1)
87 {
88 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
89 }
90 else
91 {
92 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
93 }
94
9b924220 95 # leading zeros will be stripped by _from_hex()
b282a552 96 $bx = '0x' . $bx;
9b924220 97 $x->{value} = $CALC_EMU->_from_hex( $bx );
b282a552 98
99 # calculate sign of result
100 $x->{sign} = '+';
b282a552 101 $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
102
103 $x->bdec() if $sign == 1;
104
105 $x->round(@r);
106 }
107
108sub __emu_bior
109 {
110 my ($self,$x,$y,$sx,$sy,@r) = @_;
111
112 return $x->round(@r) if $y->is_zero();
113
114 my $sign = 0; # sign of result
115 $sign = 1 if ($sx == -1) || ($sy == -1);
116
117 my ($bx,$by);
118
119 if ($sx == -1) # if x is negative
120 {
121 # two's complement: inc and flip all "bits" in $bx
122 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
123 $bx =~ s/-?0x//;
124 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
125 }
126 else
127 {
128 $bx = $x->as_hex(); # get binary representation
129 $bx =~ s/-?0x//;
130 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
131 }
132 if ($sy == -1) # if y is negative
133 {
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
136 $by =~ s/-?0x//;
137 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
138 }
139 else
140 {
141 $by = $y->as_hex(); # get binary representation
142 $by =~ s/-?0x//;
143 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
144 }
145 # now we have bit-strings from X and Y, reverse them for padding
146 $bx = reverse $bx;
147 $by = reverse $by;
148
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);
153 if ($diff > 0)
154 {
155 $by .= $yy x $diff;
156 }
157 elsif ($diff < 0)
158 {
159 $bx .= $xx x abs($diff);
160 }
161
162 # or the strings together
163 my $r = $bx | $by;
164
165 # and reverse the result again
166 $bx = reverse $r;
167
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.
171 if ($sign == 1)
172 {
173 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
174 }
175 else
176 {
177 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
178 }
179
9b924220 180 # leading zeros will be stripped by _from_hex()
b282a552 181 $bx = '0x' . $bx;
9b924220 182 $x->{value} = $CALC_EMU->_from_hex( $bx );
183
184 # calculate sign of result
185 $x->{sign} = '+';
186 $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
b282a552 187
188 # if one of X or Y was negative, we need to decrement result
189 $x->bdec() if $sign == 1;
190
191 $x->round(@r);
192 }
193
194sub __emu_bxor
195 {
196 my ($self,$x,$y,$sx,$sy,@r) = @_;
197
198 return $x->round(@r) if $y->is_zero();
199
200 my $sign = 0; # sign of result
201 $sign = 1 if $x->{sign} ne $y->{sign};
202
203 my ($bx,$by);
204
205 if ($sx == -1) # if x is negative
206 {
207 # two's complement: inc and flip all "bits" in $bx
208 $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
209 $bx =~ s/-?0x//;
210 $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
211 }
212 else
213 {
214 $bx = $x->as_hex(); # get binary representation
215 $bx =~ s/-?0x//;
216 $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
217 }
218 if ($sy == -1) # if y is negative
219 {
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
222 $by =~ s/-?0x//;
223 $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
224 }
225 else
226 {
227 $by = $y->as_hex(); # get binary representation
228 $by =~ s/-?0x//;
229 $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
230 }
231 # now we have bit-strings from X and Y, reverse them for padding
232 $bx = reverse $bx;
233 $by = reverse $by;
234
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);
239 if ($diff > 0)
240 {
241 $by .= $yy x $diff;
242 }
243 elsif ($diff < 0)
244 {
245 $bx .= $xx x abs($diff);
246 }
247
248 # xor the strings together
249 my $r = $bx ^ $by;
250
251 # and reverse the result again
252 $bx = reverse $r;
253
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.
257 if ($sign == 1)
258 {
259 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
260 }
261 else
262 {
263 $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
264 }
265
9b924220 266 # leading zeros will be stripped by _from_hex()
b282a552 267 $bx = '0x' . $bx;
9b924220 268 $x->{value} = $CALC_EMU->_from_hex( $bx );
b282a552 269
270 # calculate sign of result
271 $x->{sign} = '+';
272 $x->{sign} = '-' if $sx != $sy && !$x->is_zero();
273
274 $x->bdec() if $sign == 1;
275
276 $x->round(@r);
277 }
278
b282a552 279##############################################################################
280##############################################################################
281
2821;
283__END__
284
285=head1 NAME
286
287Math::BigInt::CalcEmu - Emulate low-level math with BigInt code
288
289=head1 SYNOPSIS
290
291Contains routines that emulate low-level math functions in BigInt, e.g.
292optional routines the low-level math package does not provide on it's own.
293
294Will be loaded on demand and automatically by BigInt.
295
296Stuff here is really low-priority to optimize,
297since it is far better to implement the operation in the low-level math
298libary directly, possible even using a call to the native lib.
299
300=head1 DESCRIPTION
301
302=head1 METHODS
303
304=head1 LICENSE
305
306This program is free software; you may redistribute it and/or modify it under
307the same terms as Perl itself.
308
309=head1 AUTHORS
310
9b924220 311(c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by
b282a552 312Tels from 2001-2003.
313
314=head1 SEE ALSO
315
316L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
317L<Math::BigInt::GMP> and L<Math::BigInt::Pari>.
318
319=cut