Commit | Line | Data |
b282a552 |
1 | package Math::BigInt; |
2 | |
3 | use 5.005; |
4 | use strict; |
5 | # use warnings; # dont use warnings for older Perls |
6 | |
7 | use vars qw/$VERSION/; |
8 | |
3a427a11 |
9 | $VERSION = '0.02'; |
b282a552 |
10 | |
11 | # See SYNOPSIS below. |
12 | |
13 | my $CALC_EMU; |
14 | |
15 | BEGIN |
16 | { |
17 | $CALC_EMU = Math::BigInt->config()->{'lib'}; |
18 | } |
19 | |
20 | sub __emu_blog |
21 | { |
22 | my ($self,$x,$base,@r) = @_; |
23 | |
24 | return $x->bnan() if $x->is_zero() || $base->is_zero() || $base->is_one(); |
25 | |
26 | my $acmp = $x->bacmp($base); |
27 | return $x->bone('+',@r) if $acmp == 0; |
28 | return $x->bzero(@r) if $acmp < 0 || $x->is_one(); |
29 | |
30 | # blog($x,$base) ** $base + $y = $x |
31 | |
32 | # this trial multiplication is very fast, even for large counts (like for |
33 | # 2 ** 1024, since this still requires only 1024 very fast steps |
34 | # (multiplication of a large number by a very small number is very fast)) |
35 | # See Calc for an even faster algorightmn |
36 | my $x_org = $x->copy(); # preserve orgx |
37 | $x->bzero(); # keep ref to $x |
38 | my $trial = $base->copy(); |
39 | while ($trial->bacmp($x_org) <= 0) |
40 | { |
41 | $trial->bmul($base); $x->binc(); |
42 | } |
43 | $x->round(@r); |
44 | } |
45 | |
46 | sub __emu_bmodinv |
47 | { |
48 | my ($self,$x,$y,@r) = @_; |
49 | |
50 | my ($u, $u1) = ($self->bzero(), $self->bone()); |
51 | my ($a, $b) = ($y->copy(), $x->copy()); |
52 | |
53 | # first step need always be done since $num (and thus $b) is never 0 |
54 | # Note that the loop is aligned so that the check occurs between #2 and #1 |
55 | # thus saving us one step #2 at the loop end. Typical loop count is 1. Even |
56 | # a case with 28 loops still gains about 3% with this layout. |
57 | my $q; |
58 | ($a, $q, $b) = ($b, $a->bdiv($b)); # step #1 |
59 | # Euclid's Algorithm (calculate GCD of ($a,$b) in $a and also calculate |
60 | # two values in $u and $u1, we use only $u1 afterwards) |
61 | my $sign = 1; # flip-flop |
62 | while (!$b->is_zero()) # found GCD if $b == 0 |
63 | { |
64 | # the original algorithm had: |
65 | # ($u, $u1) = ($u1, $u->bsub($u1->copy()->bmul($q))); # step #2 |
66 | # The following creates exact the same sequence of numbers in $u1, |
67 | # except for the sign ($u1 is now always positive). Since formerly |
68 | # the sign of $u1 was alternating between '-' and '+', the $sign |
69 | # flip-flop will take care of that, so that at the end of the loop |
70 | # we have the real sign of $u1. Keeping numbers positive gains us |
71 | # speed since badd() is faster than bsub() and makes it possible |
72 | # to have the algorithmn in Calc for even more speed. |
73 | |
74 | ($u, $u1) = ($u1, $u->badd($u1->copy()->bmul($q))); # step #2 |
75 | $sign = - $sign; # flip sign |
76 | |
77 | ($a, $q, $b) = ($b, $a->bdiv($b)); # step #1 again |
78 | } |
79 | |
80 | # If the gcd is not 1, then return NaN! It would be pointless to have |
81 | # called bgcd to check this first, because we would then be performing |
82 | # the same Euclidean Algorithm *twice* in case the gcd is 1. |
83 | return $x->bnan() unless $a->is_one(); |
84 | |
85 | $u1->bneg() if $sign != 1; # need to flip? |
86 | |
87 | $u1->bmod($y); # calc result |
88 | $x->{value} = $u1->{value}; # and copy over to $x |
89 | $x->{sign} = $u1->{sign}; # to modify in place |
90 | $x->round(@r); |
91 | } |
92 | |
93 | sub __emu_bmodpow |
94 | { |
95 | my ($self,$num,$exp,$mod,@r) = @_; |
96 | |
97 | # in the trivial case, |
98 | return $num->bzero(@r) if $mod->is_one(); |
99 | return $num->bone('+',@r) if $num->is_zero() or $num->is_one(); |
100 | |
101 | # $num->bmod($mod); # if $x is large, make it smaller first |
102 | my $acc = $num->copy(); # but this is not really faster... |
103 | |
104 | $num->bone(); # keep ref to $num |
105 | |
106 | my $expbin = $exp->as_bin(); $expbin =~ s/^[-]?0b//; # ignore sign and prefix |
107 | my $len = CORE::length($expbin); |
108 | while (--$len >= 0) |
109 | { |
110 | $num->bmul($acc)->bmod($mod) if substr($expbin,$len,1) eq '1'; |
111 | $acc->bmul($acc)->bmod($mod); |
112 | } |
113 | |
114 | $num->round(@r); |
115 | } |
116 | |
117 | sub __emu_bfac |
118 | { |
119 | my ($self,$x,@r) = @_; |
120 | |
121 | return $x->bone('+',@r) if $x->is_zero() || $x->is_one(); # 0 or 1 => 1 |
122 | |
123 | my $n = $x->copy(); |
124 | $x->bone(); |
125 | # seems we need not to temp. clear A/P of $x since the result is the same |
126 | my $f = $self->new(2); |
127 | while ($f->bacmp($n) < 0) |
128 | { |
129 | $x->bmul($f); $f->binc(); |
130 | } |
131 | $x->bmul($f,@r); # last step and also round result |
132 | } |
133 | |
134 | sub __emu_bpow |
135 | { |
136 | my ($self,$x,$y,@r) = @_; |
137 | |
138 | return $x->bone('+',@r) if $y->is_zero(); |
139 | return $x->round(@r) if $x->is_one() || $y->is_one(); |
140 | return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0) |
141 | |
142 | my $pow2 = $self->bone(); |
143 | my $y_bin = $y->as_bin(); $y_bin =~ s/^0b//; |
144 | my $len = CORE::length($y_bin); |
145 | while (--$len > 0) |
146 | { |
147 | $pow2->bmul($x) if substr($y_bin,$len,1) eq '1'; # is odd? |
148 | $x->bmul($x); |
149 | } |
150 | $x->bmul($pow2); |
151 | $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0; |
152 | $x; |
153 | } |
154 | |
155 | sub __emu_band |
156 | { |
157 | my ($self,$x,$y,$sx,$sy,@r) = @_; |
158 | |
159 | return $x->bzero(@r) if $y->is_zero() || $x->is_zero(); |
160 | |
161 | my $sign = 0; # sign of result |
162 | $sign = 1 if $sx == -1 && $sy == -1; |
163 | |
164 | my ($bx,$by); |
165 | |
166 | if ($sx == -1) # if x is negative |
167 | { |
168 | # two's complement: inc and flip all "bits" in $bx |
169 | $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc |
170 | $bx =~ s/-?0x//; |
171 | $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
172 | } |
173 | else |
174 | { |
175 | $bx = $x->as_hex(); # get binary representation |
176 | $bx =~ s/-?0x//; |
177 | $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
178 | } |
179 | if ($sy == -1) # if y is negative |
180 | { |
181 | # two's complement: inc and flip all "bits" in $by |
182 | $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc |
183 | $by =~ s/-?0x//; |
184 | $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
185 | } |
186 | else |
187 | { |
188 | $by = $y->as_hex(); # get binary representation |
189 | $by =~ s/-?0x//; |
190 | $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
191 | } |
192 | # now we have bit-strings from X and Y, reverse them for padding |
193 | $bx = reverse $bx; |
194 | $by = reverse $by; |
195 | |
196 | # cut the longer string to the length of the shorter one (the result would |
197 | # be 0 due to AND anyway) |
198 | my $diff = CORE::length($bx) - CORE::length($by); |
199 | if ($diff > 0) |
200 | { |
201 | $bx = substr($bx,0,CORE::length($by)); |
202 | } |
203 | elsif ($diff < 0) |
204 | { |
205 | $by = substr($by,0,CORE::length($bx)); |
206 | } |
207 | |
208 | # and the strings together |
209 | my $r = $bx & $by; |
210 | |
211 | # and reverse the result again |
212 | $bx = reverse $r; |
213 | |
214 | # one of $x or $y was negative, so need to flip bits in the result |
215 | # in both cases (one or two of them negative, or both positive) we need |
216 | # to get the characters back. |
217 | if ($sign == 1) |
218 | { |
219 | $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/; |
220 | } |
221 | else |
222 | { |
223 | $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/; |
224 | } |
225 | |
226 | $bx = '0x' . $bx; |
227 | if ($CALC_EMU->can('_from_hex')) |
228 | { |
229 | $x->{value} = $CALC_EMU->_from_hex( \$bx ); |
230 | } |
231 | else |
232 | { |
233 | $r = $self->new($bx); |
234 | $x->{value} = $r->{value}; |
235 | } |
236 | |
237 | # calculate sign of result |
238 | $x->{sign} = '+'; |
239 | #$x->{sign} = '-' if $sx == $sy && $sx == -1 && !$x->is_zero(); |
240 | $x->{sign} = '-' if $sign == 1 && !$x->is_zero(); |
241 | |
242 | $x->bdec() if $sign == 1; |
243 | |
244 | $x->round(@r); |
245 | } |
246 | |
247 | sub __emu_bior |
248 | { |
249 | my ($self,$x,$y,$sx,$sy,@r) = @_; |
250 | |
251 | return $x->round(@r) if $y->is_zero(); |
252 | |
253 | my $sign = 0; # sign of result |
254 | $sign = 1 if ($sx == -1) || ($sy == -1); |
255 | |
256 | my ($bx,$by); |
257 | |
258 | if ($sx == -1) # if x is negative |
259 | { |
260 | # two's complement: inc and flip all "bits" in $bx |
261 | $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc |
262 | $bx =~ s/-?0x//; |
263 | $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
264 | } |
265 | else |
266 | { |
267 | $bx = $x->as_hex(); # get binary representation |
268 | $bx =~ s/-?0x//; |
269 | $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
270 | } |
271 | if ($sy == -1) # if y is negative |
272 | { |
273 | # two's complement: inc and flip all "bits" in $by |
274 | $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc |
275 | $by =~ s/-?0x//; |
276 | $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
277 | } |
278 | else |
279 | { |
280 | $by = $y->as_hex(); # get binary representation |
281 | $by =~ s/-?0x//; |
282 | $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
283 | } |
284 | # now we have bit-strings from X and Y, reverse them for padding |
285 | $bx = reverse $bx; |
286 | $by = reverse $by; |
287 | |
288 | # padd the shorter string |
289 | my $xx = "\x00"; $xx = "\x0f" if $sx == -1; |
290 | my $yy = "\x00"; $yy = "\x0f" if $sy == -1; |
291 | my $diff = CORE::length($bx) - CORE::length($by); |
292 | if ($diff > 0) |
293 | { |
294 | $by .= $yy x $diff; |
295 | } |
296 | elsif ($diff < 0) |
297 | { |
298 | $bx .= $xx x abs($diff); |
299 | } |
300 | |
301 | # or the strings together |
302 | my $r = $bx | $by; |
303 | |
304 | # and reverse the result again |
305 | $bx = reverse $r; |
306 | |
307 | # one of $x or $y was negative, so need to flip bits in the result |
308 | # in both cases (one or two of them negative, or both positive) we need |
309 | # to get the characters back. |
310 | if ($sign == 1) |
311 | { |
312 | $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/; |
313 | } |
314 | else |
315 | { |
316 | $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/; |
317 | } |
318 | |
319 | $bx = '0x' . $bx; |
320 | if ($CALC_EMU->can('_from_hex')) |
321 | { |
322 | $x->{value} = $CALC_EMU->_from_hex( \$bx ); |
323 | } |
324 | else |
325 | { |
326 | $r = $self->new($bx); |
327 | $x->{value} = $r->{value}; |
328 | } |
329 | |
330 | # if one of X or Y was negative, we need to decrement result |
331 | $x->bdec() if $sign == 1; |
332 | |
333 | $x->round(@r); |
334 | } |
335 | |
336 | sub __emu_bxor |
337 | { |
338 | my ($self,$x,$y,$sx,$sy,@r) = @_; |
339 | |
340 | return $x->round(@r) if $y->is_zero(); |
341 | |
342 | my $sign = 0; # sign of result |
343 | $sign = 1 if $x->{sign} ne $y->{sign}; |
344 | |
345 | my ($bx,$by); |
346 | |
347 | if ($sx == -1) # if x is negative |
348 | { |
349 | # two's complement: inc and flip all "bits" in $bx |
350 | $bx = $x->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc |
351 | $bx =~ s/-?0x//; |
352 | $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
353 | } |
354 | else |
355 | { |
356 | $bx = $x->as_hex(); # get binary representation |
357 | $bx =~ s/-?0x//; |
358 | $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
359 | } |
360 | if ($sy == -1) # if y is negative |
361 | { |
362 | # two's complement: inc and flip all "bits" in $by |
363 | $by = $y->copy()->binc()->as_hex(); # -1 => 0, -2 => 1, -3 => 2 etc |
364 | $by =~ s/-?0x//; |
365 | $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
366 | } |
367 | else |
368 | { |
369 | $by = $y->as_hex(); # get binary representation |
370 | $by =~ s/-?0x//; |
371 | $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/; |
372 | } |
373 | # now we have bit-strings from X and Y, reverse them for padding |
374 | $bx = reverse $bx; |
375 | $by = reverse $by; |
376 | |
377 | # padd the shorter string |
378 | my $xx = "\x00"; $xx = "\x0f" if $sx == -1; |
379 | my $yy = "\x00"; $yy = "\x0f" if $sy == -1; |
380 | my $diff = CORE::length($bx) - CORE::length($by); |
381 | if ($diff > 0) |
382 | { |
383 | $by .= $yy x $diff; |
384 | } |
385 | elsif ($diff < 0) |
386 | { |
387 | $bx .= $xx x abs($diff); |
388 | } |
389 | |
390 | # xor the strings together |
391 | my $r = $bx ^ $by; |
392 | |
393 | # and reverse the result again |
394 | $bx = reverse $r; |
395 | |
396 | # one of $x or $y was negative, so need to flip bits in the result |
397 | # in both cases (one or two of them negative, or both positive) we need |
398 | # to get the characters back. |
399 | if ($sign == 1) |
400 | { |
401 | $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/; |
402 | } |
403 | else |
404 | { |
405 | $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/; |
406 | } |
407 | |
408 | $bx = '0x' . $bx; |
409 | if ($CALC_EMU->can('_from_hex')) |
410 | { |
411 | $x->{value} = $CALC_EMU->_from_hex( \$bx ); |
412 | } |
413 | else |
414 | { |
415 | $r = $self->new($bx); |
416 | $x->{value} = $r->{value}; |
417 | } |
418 | |
419 | # calculate sign of result |
420 | $x->{sign} = '+'; |
421 | $x->{sign} = '-' if $sx != $sy && !$x->is_zero(); |
422 | |
423 | $x->bdec() if $sign == 1; |
424 | |
425 | $x->round(@r); |
426 | } |
427 | |
428 | sub __emu_bsqrt |
429 | { |
430 | my ($self,$x,@r) = @_; |
431 | |
432 | # this is slow: |
433 | return $x->round(@r) if $x->is_zero(); # 0,1 => 0,1 |
434 | |
435 | return $x->bone('+',@r) if $x < 4; # 1,2,3 => 1 |
436 | my $y = $x->copy(); |
437 | my $l = int($x->length()/2); |
438 | |
439 | $x->bone(); # keep ref($x), but modify it |
440 | $x->blsft($l,10) if $l != 0; # first guess: 1.('0' x (l/2)) |
441 | |
442 | my $last = $self->bzero(); |
443 | my $two = $self->new(2); |
444 | my $lastlast = $self->bzero(); |
445 | #my $lastlast = $x+$two; |
446 | while ($last != $x && $lastlast != $x) |
447 | { |
448 | $lastlast = $last; $last = $x->copy(); |
449 | $x->badd($y / $x); |
450 | $x->bdiv($two); |
451 | } |
452 | $x->bdec() if $x * $x > $y; # overshot? |
453 | $x->round(@r); |
454 | } |
455 | |
456 | sub __emu_broot |
457 | { |
458 | my ($self,$x,$y,@r) = @_; |
459 | |
460 | return $x->bsqrt() if $y->bacmp(2) == 0; # 2 => square root |
461 | |
462 | # since we take at least a cubic root, and only 8 ** 1/3 >= 2 (==2): |
463 | return $x->bone('+',@r) if $x < 8; # $x=2..7 => 1 |
464 | |
465 | my $num = $x->numify(); |
466 | |
467 | if ($num <= 1000000) |
468 | { |
469 | $x = $self->new( int ( sprintf ("%.8f", $num ** (1 / $y->numify() )))); |
470 | return $x->round(@r); |
471 | } |
472 | |
473 | # if $n is a power of two, we can repeatedly take sqrt($X) and find the |
474 | # proper result, because sqrt(sqrt($x)) == root($x,4) |
475 | # See Calc.pm for more details |
476 | my $b = $y->as_bin(); |
3a427a11 |
477 | if ($b =~ /0b1(0+)$/) |
b282a552 |
478 | { |
479 | my $count = CORE::length($1); # 0b100 => len('00') => 2 |
480 | my $cnt = $count; # counter for loop |
481 | my $shift = $self->new(6); |
482 | $x->blsft($shift); # add some zeros (even amount) |
483 | while ($cnt-- > 0) |
484 | { |
485 | # 'inflate' $X by adding more zeros |
486 | $x->blsft($shift); |
487 | # calculate sqrt($x), $x is now a bit too big, again. In the next |
488 | # round we make even bigger, again. |
489 | $x->bsqrt($x); |
490 | } |
491 | # $x is still to big, so truncate result |
492 | $x->brsft($shift); |
493 | } |
494 | else |
495 | { |
3a427a11 |
496 | # trial computation by starting with 2,4,6,8,10 etc until we overstep |
497 | my $step; |
498 | my $trial = $self->new(2); |
499 | my $two = $self->new(2); |
500 | my $s_128 = $self->new(128); |
501 | |
502 | local undef $Math::BigInt::accuracy; |
503 | local undef $Math::BigInt::precision; |
504 | |
505 | # while still to do more than X steps |
506 | do |
507 | { |
508 | $step = $self->new(2); |
509 | while ( $trial->copy->bpow($y)->bacmp($x) < 0) |
510 | { |
511 | $step->bmul($two); |
512 | $trial->badd($step); |
513 | } |
514 | |
515 | # hit exactly? |
516 | if ( $trial->copy->bpow($y)->bacmp($x) == 0) |
517 | { |
518 | $x->{value} = $trial->{value}; # make copy while preserving ref to $x |
519 | return $x->round(@r); |
520 | } |
521 | # overstepped, so go back on step |
522 | $trial->bsub($step); |
523 | } while ($step > $s_128); |
524 | |
525 | $step = $two->copy(); |
526 | while ( $trial->copy->bpow($y)->bacmp($x) < 0) |
527 | { |
528 | $trial->badd($step); |
529 | } |
530 | |
531 | # not hit exactly? |
532 | if ( $x->bacmp( $trial->copy()->bpow($y) ) < 0) |
533 | { |
534 | $trial->bdec(); |
535 | } |
536 | # copy result into $x (preserve ref) |
537 | $x->{value} = $trial->{value}; |
b282a552 |
538 | } |
539 | $x->round(@r); |
540 | } |
541 | |
542 | sub __emu_as_hex |
543 | { |
544 | my ($self,$x,$s) = @_; |
545 | |
546 | return '0x0' if $x->is_zero(); |
547 | |
548 | my $x1 = $x->copy()->babs(); my ($xr,$x10000,$h,$es); |
549 | if ($] >= 5.006) |
550 | { |
551 | $x10000 = $self->new (0x10000); $h = 'h4'; |
552 | } |
553 | else |
554 | { |
555 | $x10000 = $self->new (0x1000); $h = 'h3'; |
556 | } |
557 | while (!$x1->is_zero()) |
558 | { |
559 | ($x1, $xr) = bdiv($x1,$x10000); |
560 | $es .= unpack($h,pack('v',$xr->numify())); |
561 | } |
562 | $es = reverse $es; |
563 | $es =~ s/^[0]+//; # strip leading zeros |
564 | $s . '0x' . $es; |
565 | } |
566 | |
567 | sub __emu_as_bin |
568 | { |
569 | my ($self,$x,$s) = @_; |
570 | |
571 | return '0b0' if $x->is_zero(); |
572 | |
573 | my $x1 = $x->copy()->babs(); my ($xr,$x10000,$b,$es); |
574 | if ($] >= 5.006) |
575 | { |
576 | $x10000 = $self->new (0x10000); $b = 'b16'; |
577 | } |
578 | else |
579 | { |
580 | $x10000 = $self->new (0x1000); $b = 'b12'; |
581 | } |
582 | while (!$x1->is_zero()) |
583 | { |
584 | ($x1, $xr) = bdiv($x1,$x10000); |
585 | $es .= unpack($b,pack('v',$xr->numify())); |
586 | } |
587 | $es = reverse $es; |
588 | $es =~ s/^[0]+//; # strip leading zeros |
589 | $s . '0b' . $es; |
590 | } |
591 | |
592 | ############################################################################## |
593 | ############################################################################## |
594 | |
595 | 1; |
596 | __END__ |
597 | |
598 | =head1 NAME |
599 | |
600 | Math::BigInt::CalcEmu - Emulate low-level math with BigInt code |
601 | |
602 | =head1 SYNOPSIS |
603 | |
604 | Contains routines that emulate low-level math functions in BigInt, e.g. |
605 | optional routines the low-level math package does not provide on it's own. |
606 | |
607 | Will be loaded on demand and automatically by BigInt. |
608 | |
609 | Stuff here is really low-priority to optimize, |
610 | since it is far better to implement the operation in the low-level math |
611 | libary directly, possible even using a call to the native lib. |
612 | |
613 | =head1 DESCRIPTION |
614 | |
615 | =head1 METHODS |
616 | |
617 | =head1 LICENSE |
618 | |
619 | This program is free software; you may redistribute it and/or modify it under |
620 | the same terms as Perl itself. |
621 | |
622 | =head1 AUTHORS |
623 | |
624 | (c) Tels http://bloodgate.com 2003 - based on BigInt code by |
625 | Tels from 2001-2003. |
626 | |
627 | =head1 SEE ALSO |
628 | |
629 | L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>, |
630 | L<Math::BigInt::GMP> and L<Math::BigInt::Pari>. |
631 | |
632 | =cut |