ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/Math/BigInt/CalcEmu.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:13 2005 UTC (21 years, 4 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 package Math::BigInt::CalcEmu;
2    
3     use 5.005;
4     use strict;
5     # use warnings; # dont use warnings for older Perls
6     use vars qw/$VERSION/;
7    
8     $VERSION = '0.05';
9    
10     package Math::BigInt;
11    
12     # See SYNOPSIS below.
13    
14     my $CALC_EMU;
15    
16     BEGIN
17     {
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]; } );
21     }
22    
23     sub __emu_band
24     {
25     my ($self,$x,$y,$sx,$sy,@r) = @_;
26    
27     return $x->bzero(@r) if $y->is_zero() || $x->is_zero();
28    
29     my $sign = 0; # sign of result
30     $sign = 1 if $sx == -1 && $sy == -1;
31    
32     my ($bx,$by);
33    
34     if ($sx == -1) # if x is negative
35     {
36     # two's complement: inc and flip all "bits" in $bx
37     $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
38     $bx =~ s/-?0x//;
39     $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
40     }
41     else
42     {
43     $bx = $x->as_hex(); # get binary representation
44     $bx =~ s/-?0x//;
45     $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
46     }
47     if ($sy == -1) # if y is negative
48     {
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
51     $by =~ s/-?0x//;
52     $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
53     }
54     else
55     {
56     $by = $y->as_hex(); # get binary representation
57     $by =~ s/-?0x//;
58     $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
59     }
60     # now we have bit-strings from X and Y, reverse them for padding
61     $bx = reverse $bx;
62     $by = reverse $by;
63    
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);
68     if ($diff > 0)
69     {
70     # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
71     $by .= $yy x $diff;
72     }
73     elsif ($diff < 0)
74     {
75     # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
76     $bx .= $xx x abs($diff);
77     }
78    
79     # and the strings together
80     my $r = $bx & $by;
81    
82     # and reverse the result again
83     $bx = reverse $r;
84    
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.
88     if ($sign == 1)
89     {
90     $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
91     }
92     else
93     {
94     $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
95     }
96    
97     # leading zeros will be stripped by _from_hex()
98     $bx = '0x' . $bx;
99     $x->{value} = $CALC_EMU->_from_hex( $bx );
100    
101     # calculate sign of result
102     $x->{sign} = '+';
103     $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
104    
105     $x->bdec() if $sign == 1;
106    
107     $x->round(@r);
108     }
109    
110     sub __emu_bior
111     {
112     my ($self,$x,$y,$sx,$sy,@r) = @_;
113    
114     return $x->round(@r) if $y->is_zero();
115    
116     my $sign = 0; # sign of result
117     $sign = 1 if ($sx == -1) || ($sy == -1);
118    
119     my ($bx,$by);
120    
121     if ($sx == -1) # if x is negative
122     {
123     # two's complement: inc and flip all "bits" in $bx
124     $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
125     $bx =~ s/-?0x//;
126     $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
127     }
128     else
129     {
130     $bx = $x->as_hex(); # get binary representation
131     $bx =~ s/-?0x//;
132     $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
133     }
134     if ($sy == -1) # if y is negative
135     {
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
138     $by =~ s/-?0x//;
139     $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
140     }
141     else
142     {
143     $by = $y->as_hex(); # get binary representation
144     $by =~ s/-?0x//;
145     $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
146     }
147     # now we have bit-strings from X and Y, reverse them for padding
148     $bx = reverse $bx;
149     $by = reverse $by;
150    
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);
155     if ($diff > 0)
156     {
157     $by .= $yy x $diff;
158     }
159     elsif ($diff < 0)
160     {
161     $bx .= $xx x abs($diff);
162     }
163    
164     # or the strings together
165     my $r = $bx | $by;
166    
167     # and reverse the result again
168     $bx = reverse $r;
169    
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.
173     if ($sign == 1)
174     {
175     $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
176     }
177     else
178     {
179     $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
180     }
181    
182     # leading zeros will be stripped by _from_hex()
183     $bx = '0x' . $bx;
184     $x->{value} = $CALC_EMU->_from_hex( $bx );
185    
186     # calculate sign of result
187     $x->{sign} = '+';
188     $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
189    
190     # if one of X or Y was negative, we need to decrement result
191     $x->bdec() if $sign == 1;
192    
193     $x->round(@r);
194     }
195    
196     sub __emu_bxor
197     {
198     my ($self,$x,$y,$sx,$sy,@r) = @_;
199    
200     return $x->round(@r) if $y->is_zero();
201    
202     my $sign = 0; # sign of result
203     $sign = 1 if $x->{sign} ne $y->{sign};
204    
205     my ($bx,$by);
206    
207     if ($sx == -1) # if x is negative
208     {
209     # two's complement: inc and flip all "bits" in $bx
210     $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc
211     $bx =~ s/-?0x//;
212     $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
213     }
214     else
215     {
216     $bx = $x->as_hex(); # get binary representation
217     $bx =~ s/-?0x//;
218     $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
219     }
220     if ($sy == -1) # if y is negative
221     {
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
224     $by =~ s/-?0x//;
225     $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
226     }
227     else
228     {
229     $by = $y->as_hex(); # get binary representation
230     $by =~ s/-?0x//;
231     $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
232     }
233     # now we have bit-strings from X and Y, reverse them for padding
234     $bx = reverse $bx;
235     $by = reverse $by;
236    
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);
241     if ($diff > 0)
242     {
243     $by .= $yy x $diff;
244     }
245     elsif ($diff < 0)
246     {
247     $bx .= $xx x abs($diff);
248     }
249    
250     # xor the strings together
251     my $r = $bx ^ $by;
252    
253     # and reverse the result again
254     $bx = reverse $r;
255    
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.
259     if ($sign == 1)
260     {
261     $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
262     }
263     else
264     {
265     $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
266     }
267    
268     # leading zeros will be stripped by _from_hex()
269     $bx = '0x' . $bx;
270     $x->{value} = $CALC_EMU->_from_hex( $bx );
271    
272     # calculate sign of result
273     $x->{sign} = '+';
274     $x->{sign} = '-' if $sx != $sy && !$x->is_zero();
275    
276     $x->bdec() if $sign == 1;
277    
278     $x->round(@r);
279     }
280    
281     ##############################################################################
282     ##############################################################################
283    
284     1;
285     __END__
286    
287     =head1 NAME
288    
289     Math::BigInt::CalcEmu - Emulate low-level math with BigInt code
290    
291     =head1 SYNOPSIS
292    
293     use Math::BigInt::CalcEmu;
294    
295     =head1 DESCRIPTION
296    
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.
299    
300     Will be loaded on demand and called automatically by BigInt.
301    
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.
305    
306     =head1 METHODS
307    
308     =head2 __emu_bxor
309    
310     =head2 __emu_band
311    
312     =head2 __emu_bior
313    
314     =head1 LICENSE
315    
316     This program is free software; you may redistribute it and/or modify it under
317     the same terms as Perl itself.
318    
319     =head1 AUTHORS
320    
321     (c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by
322     Tels from 2001-2003.
323    
324     =head1 SEE ALSO
325    
326     L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
327     L<Math::BigInt::GMP> and L<Math::BigInt::Pari>.
328    
329     =cut