Commit | Line | Data |
---|---|---|
126f3c5f | 1 | package bigrat; |
9de9b613 | 2 | use 5.006; |
126f3c5f | 3 | |
bcb1dae1 | 4 | $VERSION = '0.27'; |
b68b7ab1 | 5 | require Exporter; |
d1a15766 | 6 | @ISA = qw( bigint ); |
d98d5fa0 T |
7 | @EXPORT_OK = qw( PI e bpi bexp ); |
8 | @EXPORT = qw( inf NaN ); | |
126f3c5f JH |
9 | |
10 | use strict; | |
95a2d02c | 11 | use overload; |
d1a15766 | 12 | require bigint; # no "use" to avoid callind import |
126f3c5f JH |
13 | |
14 | ############################################################################## | |
15 | ||
d1a15766 T |
16 | BEGIN |
17 | { | |
18 | *inf = \&bigint::inf; | |
19 | *NaN = \&bigint::NaN; | |
20 | } | |
21 | ||
126f3c5f JH |
22 | # These are all alike, and thus faked by AUTOLOAD |
23 | ||
24 | my @faked = qw/round_mode accuracy precision div_scale/; | |
25 | use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite | |
26 | ||
27 | sub AUTOLOAD | |
28 | { | |
29 | my $name = $AUTOLOAD; | |
30 | ||
31 | $name =~ s/.*:://; # split package | |
32 | no strict 'refs'; | |
33 | foreach my $n (@faked) | |
34 | { | |
35 | if ($n eq $name) | |
36 | { | |
37 | *{"bigrat::$name"} = sub | |
38 | { | |
39 | my $self = shift; | |
40 | no strict 'refs'; | |
41 | if (defined $_[0]) | |
42 | { | |
43 | Math::BigInt->$name($_[0]); | |
44 | Math::BigFloat->$name($_[0]); | |
990fb837 | 45 | return Math::BigRat->$name($_[0]); |
126f3c5f JH |
46 | } |
47 | return Math::BigInt->$name(); | |
48 | }; | |
49 | return &$name; | |
50 | } | |
51 | } | |
52 | ||
53 | # delayed load of Carp and avoid recursion | |
54 | require Carp; | |
55 | Carp::croak ("Can't call bigrat\-\>$name, not a valid method"); | |
56 | } | |
57 | ||
4440d13a T |
58 | sub unimport |
59 | { | |
60 | $^H{bigrat} = undef; # no longer in effect | |
61 | overload::remove_constant('binary','','float','','integer'); | |
62 | } | |
63 | ||
64 | sub in_effect | |
65 | { | |
66 | my $level = shift || 0; | |
67 | my $hinthash = (caller($level))[10]; | |
68 | $hinthash->{bigrat}; | |
69 | } | |
70 | ||
d1a15766 T |
71 | ############################################################################# |
72 | # the following two routines are for Perl 5.9.4 or later and are lexical | |
73 | ||
74 | sub _hex | |
75 | { | |
76 | return CORE::hex($_[0]) unless in_effect(1); | |
77 | my $i = $_[0]; | |
78 | $i = '0x'.$i unless $i =~ /^0x/; | |
79 | Math::BigInt->new($i); | |
80 | } | |
81 | ||
82 | sub _oct | |
83 | { | |
84 | return CORE::oct($_[0]) unless in_effect(1); | |
85 | my $i = $_[0]; | |
86 | return Math::BigInt->from_oct($i) if $i =~ /^0[0-7]/; | |
87 | Math::BigInt->new($i); | |
88 | } | |
89 | ||
126f3c5f JH |
90 | sub import |
91 | { | |
92 | my $self = shift; | |
93 | ||
94 | # see also bignum->import() for additional comments | |
95 | ||
4440d13a T |
96 | $^H{bigrat} = 1; # we are in effect |
97 | ||
075d4edd | 98 | my ($hex,$oct); |
d1a15766 T |
99 | # for newer Perls always override hex() and oct() with a lexical version: |
100 | if ($] > 5.009004) | |
101 | { | |
075d4edd RGS |
102 | $oct = \&_oct; |
103 | $hex = \&_hex; | |
d1a15766 | 104 | } |
126f3c5f | 105 | # some defaults |
bd49aa09 | 106 | my $lib = ''; my $lib_kind = 'try'; my $upgrade = 'Math::BigFloat'; |
126f3c5f JH |
107 | |
108 | my @import = ( ':constant' ); # drive it w/ constant | |
109 | my @a = @_; my $l = scalar @_; my $j = 0; | |
110 | my ($a,$p); | |
111 | my ($ver,$trace); # version? trace? | |
112 | for ( my $i = 0; $i < $l ; $i++,$j++ ) | |
113 | { | |
114 | if ($_[$i] eq 'upgrade') | |
115 | { | |
116 | # this causes upgrading | |
117 | $upgrade = $_[$i+1]; # or undef to disable | |
c4a6f826 | 118 | my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existent..." |
126f3c5f JH |
119 | splice @a, $j, $s; $j -= $s; |
120 | } | |
bd49aa09 | 121 | elsif ($_[$i] =~ /^(l|lib|try|only)$/) |
126f3c5f JH |
122 | { |
123 | # this causes a different low lib to take care... | |
bd49aa09 | 124 | $lib_kind = $1; $lib_kind = 'lib' if $lib_kind eq 'l'; |
126f3c5f | 125 | $lib = $_[$i+1] || ''; |
c4a6f826 | 126 | my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existent..." |
b68b7ab1 T |
127 | splice @a, $j, $s; $j -= $s; $i++; |
128 | } | |
129 | elsif ($_[$i] =~ /^(a|accuracy)$/) | |
130 | { | |
131 | $a = $_[$i+1]; | |
c4a6f826 | 132 | my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existent..." |
b68b7ab1 T |
133 | splice @a, $j, $s; $j -= $s; $i++; |
134 | } | |
135 | elsif ($_[$i] =~ /^(p|precision)$/) | |
136 | { | |
137 | $p = $_[$i+1]; | |
c4a6f826 | 138 | my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existent..." |
b68b7ab1 | 139 | splice @a, $j, $s; $j -= $s; $i++; |
126f3c5f JH |
140 | } |
141 | elsif ($_[$i] =~ /^(v|version)$/) | |
142 | { | |
143 | $ver = 1; | |
144 | splice @a, $j, 1; $j --; | |
145 | } | |
146 | elsif ($_[$i] =~ /^(t|trace)$/) | |
147 | { | |
148 | $trace = 1; | |
149 | splice @a, $j, 1; $j --; | |
150 | } | |
d1a15766 T |
151 | elsif ($_[$i] eq 'hex') |
152 | { | |
153 | splice @a, $j, 1; $j --; | |
075d4edd | 154 | $hex = \&bigint::_hex_global; |
d1a15766 T |
155 | } |
156 | elsif ($_[$i] eq 'oct') | |
157 | { | |
158 | splice @a, $j, 1; $j --; | |
075d4edd | 159 | $oct = \&bigint::_oct_global; |
d1a15766 | 160 | } |
d98d5fa0 | 161 | elsif ($_[$i] !~ /^(PI|e|bpi|bexp)\z/) |
126f3c5f JH |
162 | { |
163 | die ("unknown option $_[$i]"); | |
164 | } | |
165 | } | |
166 | my $class; | |
167 | $_lite = 0; # using M::BI::L ? | |
168 | if ($trace) | |
169 | { | |
170 | require Math::BigInt::Trace; $class = 'Math::BigInt::Trace'; | |
171 | $upgrade = 'Math::BigFloat::Trace'; | |
126f3c5f JH |
172 | } |
173 | else | |
174 | { | |
175 | # see if we can find Math::BigInt::Lite | |
176 | if (!defined $a && !defined $p) # rounding won't work to well | |
177 | { | |
178 | eval 'require Math::BigInt::Lite;'; | |
179 | if ($@ eq '') | |
180 | { | |
181 | @import = ( ); # :constant in Lite, not MBI | |
182 | Math::BigInt::Lite->import( ':constant' ); | |
183 | $_lite= 1; # signal okay | |
184 | } | |
185 | } | |
186 | require Math::BigInt if $_lite == 0; # not already loaded? | |
187 | $class = 'Math::BigInt'; # regardless of MBIL or not | |
188 | } | |
bd49aa09 | 189 | push @import, $lib_kind => $lib if $lib ne ''; |
126f3c5f | 190 | # Math::BigInt::Trace or plain Math::BigInt |
233f7bc0 | 191 | $class->import(@import, upgrade => $upgrade); |
126f3c5f JH |
192 | |
193 | require Math::BigFloat; | |
194 | Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' ); | |
195 | require Math::BigRat; | |
b68b7ab1 T |
196 | |
197 | bigrat->accuracy($a) if defined $a; | |
198 | bigrat->precision($p) if defined $p; | |
126f3c5f JH |
199 | if ($ver) |
200 | { | |
201 | print "bigrat\t\t\t v$VERSION\n"; | |
202 | print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; | |
203 | print "Math::BigInt\t\t v$Math::BigInt::VERSION"; | |
204 | my $config = Math::BigInt->config(); | |
205 | print " lib => $config->{lib} v$config->{lib_version}\n"; | |
206 | print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n"; | |
207 | print "Math::BigRat\t\t v$Math::BigRat::VERSION\n"; | |
208 | exit; | |
209 | } | |
95a2d02c T |
210 | |
211 | # Take care of octal/hexadecimal constants | |
d1a15766 | 212 | overload::constant binary => sub { bigint::_binary_constant(shift) }; |
95a2d02c | 213 | |
4440d13a T |
214 | # if another big* was already loaded: |
215 | my ($package) = caller(); | |
216 | ||
217 | no strict 'refs'; | |
218 | if (!defined *{"${package}::inf"}) | |
219 | { | |
220 | $self->export_to_level(1,$self,@a); # export inf and NaN | |
221 | } | |
075d4edd RGS |
222 | { |
223 | no warnings 'redefine'; | |
224 | *CORE::GLOBAL::oct = $oct if $oct; | |
225 | *CORE::GLOBAL::hex = $hex if $hex; | |
226 | } | |
126f3c5f JH |
227 | } |
228 | ||
d98d5fa0 T |
229 | sub PI () { Math::BigFloat->new('3.141592653589793238462643383279502884197'); } |
230 | sub e () { Math::BigFloat->new('2.718281828459045235360287471352662497757'); } | |
231 | ||
232 | sub bpi ($) { local $Math::BigFloat::upgrade; Math::BigFloat::bpi(@_); } | |
233 | ||
234 | sub bexp ($$) | |
235 | { | |
236 | local $Math::BigFloat::upgrade; | |
237 | my $x = Math::BigFloat->new($_[0]); $x->bexp($_[1]); | |
238 | } | |
fade31f0 | 239 | |
126f3c5f JH |
240 | 1; |
241 | ||
242 | __END__ | |
243 | ||
244 | =head1 NAME | |
245 | ||
b1f79218 | 246 | bigrat - Transparent BigNumber/BigRational support for Perl |
126f3c5f JH |
247 | |
248 | =head1 SYNOPSIS | |
249 | ||
250 | use bigrat; | |
251 | ||
4440d13a | 252 | print 2 + 4.5,"\n"; # BigFloat 6.5 |
126f3c5f JH |
253 | print 1/3 + 1/4,"\n"; # produces 7/12 |
254 | ||
4440d13a T |
255 | { |
256 | no bigrat; | |
257 | print 1/3,"\n"; # 0.33333... | |
258 | } | |
259 | ||
c4a6f826 | 260 | # Note that this will make hex() and oct() be globally overridden: |
d1a15766 T |
261 | use bigrat qw/hex oct/; |
262 | print hex("0x1234567890123490"),"\n"; | |
263 | print oct("01234567890123490"),"\n"; | |
264 | ||
126f3c5f JH |
265 | =head1 DESCRIPTION |
266 | ||
3c4b39be | 267 | All operators (including basic math operations) are overloaded. Integer and |
126f3c5f JH |
268 | floating-point constants are created as proper BigInts or BigFloats, |
269 | respectively. | |
270 | ||
271 | Other than L<bignum>, this module upgrades to Math::BigRat, meaning that | |
272 | instead of 2.5 you will get 2+1/2 as output. | |
273 | ||
b68b7ab1 | 274 | =head2 Modules Used |
126f3c5f JH |
275 | |
276 | C<bigrat> is just a thin wrapper around various modules of the Math::BigInt | |
277 | family. Think of it as the head of the family, who runs the shop, and orders | |
278 | the others to do the work. | |
279 | ||
280 | The following modules are currently used by bignum: | |
281 | ||
282 | Math::BigInt::Lite (for speed, and only if it is loadable) | |
283 | Math::BigInt | |
284 | Math::BigFloat | |
285 | Math::BigRat | |
286 | ||
b68b7ab1 | 287 | =head2 Math Library |
126f3c5f JH |
288 | |
289 | Math with the numbers is done (by default) by a module called | |
290 | Math::BigInt::Calc. This is equivalent to saying: | |
291 | ||
292 | use bigrat lib => 'Calc'; | |
293 | ||
294 | You can change this by using: | |
295 | ||
bd49aa09 | 296 | use bignum lib => 'GMP'; |
126f3c5f JH |
297 | |
298 | The following would first try to find Math::BigInt::Foo, then | |
299 | Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: | |
300 | ||
301 | use bigrat lib => 'Foo,Math::BigInt::Bar'; | |
302 | ||
bd49aa09 SP |
303 | Using C<lib> warns if none of the specified libraries can be found and |
304 | L<Math::BigInt> did fall back to one of the default libraries. | |
c4a6f826 | 305 | To suppress this warning, use C<try> instead: |
bd49aa09 SP |
306 | |
307 | use bignum try => 'GMP'; | |
308 | ||
309 | If you want the code to die instead of falling back, use C<only> instead: | |
310 | ||
311 | use bignum only => 'GMP'; | |
312 | ||
126f3c5f JH |
313 | Please see respective module documentation for further details. |
314 | ||
b68b7ab1 | 315 | =head2 Sign |
126f3c5f | 316 | |
b68b7ab1 | 317 | The sign is either '+', '-', 'NaN', '+inf' or '-inf'. |
126f3c5f JH |
318 | |
319 | A sign of 'NaN' is used to represent the result when input arguments are not | |
320 | numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively | |
321 | minus infinity. You will get '+inf' when dividing a positive number by 0, and | |
322 | '-inf' when dividing any negative number by 0. | |
323 | ||
b68b7ab1 | 324 | =head2 Methods |
126f3c5f JH |
325 | |
326 | Since all numbers are not objects, you can use all functions that are part of | |
327 | the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not | |
c4a6f826 | 328 | the fxxx() notation, though. This makes you independent on the fact that the |
126f3c5f JH |
329 | underlying object might morph into a different class than BigFloat. |
330 | ||
95a2d02c T |
331 | =over 2 |
332 | ||
333 | =item inf() | |
334 | ||
335 | A shortcut to return Math::BigInt->binf(). Useful because Perl does not always | |
336 | handle bareword C<inf> properly. | |
337 | ||
338 | =item NaN() | |
339 | ||
340 | A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always | |
341 | handle bareword C<NaN> properly. | |
342 | ||
d98d5fa0 T |
343 | =item e |
344 | ||
345 | # perl -Mbigrat=e -wle 'print e' | |
346 | ||
347 | Returns Euler's number C<e>, aka exp(1). | |
348 | ||
349 | =item PI | |
350 | ||
351 | # perl -Mbigrat=PI -wle 'print PI' | |
352 | ||
353 | Returns PI. | |
354 | ||
355 | =item bexp() | |
356 | ||
357 | bexp($power,$accuracy); | |
358 | ||
359 | ||
360 | Returns Euler's number C<e> raised to the appropriate power, to | |
361 | the wanted accuracy. | |
362 | ||
363 | Example: | |
364 | ||
365 | # perl -Mbigrat=bexp -wle 'print bexp(1,80)' | |
366 | ||
367 | =item bpi() | |
368 | ||
369 | bpi($accuracy); | |
fade31f0 | 370 | |
d98d5fa0 | 371 | Returns PI to the wanted accuracy. |
fade31f0 | 372 | |
d98d5fa0 | 373 | Example: |
fade31f0 | 374 | |
d98d5fa0 | 375 | # perl -Mbigrat=bpi -wle 'print bpi(80)' |
fade31f0 | 376 | |
95a2d02c T |
377 | =item upgrade() |
378 | ||
379 | Return the class that numbers are upgraded to, is in fact returning | |
380 | C<$Math::BigInt::upgrade>. | |
381 | ||
4440d13a T |
382 | =item in_effect() |
383 | ||
384 | use bigrat; | |
385 | ||
386 | print "in effect\n" if bigrat::in_effect; # true | |
387 | { | |
388 | no bigrat; | |
389 | print "in effect\n" if bigrat::in_effect; # false | |
390 | } | |
391 | ||
392 | Returns true or false if C<bigrat> is in effect in the current scope. | |
393 | ||
394 | This method only works on Perl v5.9.4 or later. | |
395 | ||
95a2d02c T |
396 | =back |
397 | ||
398 | =head2 MATH LIBRARY | |
399 | ||
400 | Math with the numbers is done (by default) by a module called | |
401 | ||
c4a6f826 | 402 | =head2 Caveat |
990fb837 RGS |
403 | |
404 | But a warning is in order. When using the following to make a copy of a number, | |
405 | only a shallow copy will be made. | |
406 | ||
407 | $x = 9; $y = $x; | |
408 | $x = $y = 7; | |
409 | ||
b68b7ab1 T |
410 | If you want to make a real copy, use the following: |
411 | ||
412 | $y = $x->copy(); | |
413 | ||
990fb837 RGS |
414 | Using the copy or the original with overloaded math is okay, e.g. the |
415 | following work: | |
416 | ||
417 | $x = 9; $y = $x; | |
418 | print $x + 1, " ", $y,"\n"; # prints 10 9 | |
419 | ||
420 | but calling any method that modifies the number directly will result in | |
3c4b39be | 421 | B<both> the original and the copy being destroyed: |
990fb837 RGS |
422 | |
423 | $x = 9; $y = $x; | |
424 | print $x->badd(1), " ", $y,"\n"; # prints 10 10 | |
425 | ||
426 | $x = 9; $y = $x; | |
427 | print $x->binc(1), " ", $y,"\n"; # prints 10 10 | |
428 | ||
429 | $x = 9; $y = $x; | |
430 | print $x->bmul(2), " ", $y,"\n"; # prints 18 18 | |
431 | ||
432 | Using methods that do not modify, but testthe contents works: | |
433 | ||
434 | $x = 9; $y = $x; | |
435 | $z = 9 if $x->is_zero(); # works fine | |
436 | ||
437 | See the documentation about the copy constructor and C<=> in overload, as | |
438 | well as the documentation in BigInt for further details. | |
439 | ||
b68b7ab1 T |
440 | =head2 Options |
441 | ||
442 | bignum recognizes some options that can be passed while loading it via use. | |
443 | The options can (currently) be either a single letter form, or the long form. | |
444 | The following options exist: | |
445 | ||
446 | =over 2 | |
447 | ||
448 | =item a or accuracy | |
449 | ||
450 | This sets the accuracy for all math operations. The argument must be greater | |
451 | than or equal to zero. See Math::BigInt's bround() function for details. | |
452 | ||
453 | perl -Mbigrat=a,50 -le 'print sqrt(20)' | |
454 | ||
c4a6f826 | 455 | Note that setting precision and accuracy at the same time is not possible. |
95a2d02c | 456 | |
b68b7ab1 T |
457 | =item p or precision |
458 | ||
459 | This sets the precision for all math operations. The argument can be any | |
460 | integer. Negative values mean a fixed number of digits after the dot, while | |
461 | a positive value rounds to this digit left from the dot. 0 or 1 mean round to | |
462 | integer. See Math::BigInt's bfround() function for details. | |
463 | ||
464 | perl -Mbigrat=p,-50 -le 'print sqrt(20)' | |
465 | ||
c4a6f826 | 466 | Note that setting precision and accuracy at the same time is not possible. |
95a2d02c | 467 | |
b68b7ab1 T |
468 | =item t or trace |
469 | ||
470 | This enables a trace mode and is primarily for debugging bignum or | |
471 | Math::BigInt/Math::BigFloat. | |
472 | ||
473 | =item l or lib | |
474 | ||
475 | Load a different math lib, see L<MATH LIBRARY>. | |
476 | ||
477 | perl -Mbigrat=l,GMP -e 'print 2 ** 512' | |
478 | ||
479 | Currently there is no way to specify more than one library on the command | |
95a2d02c T |
480 | line. This means the following does not work: |
481 | ||
482 | perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512' | |
483 | ||
484 | This will be hopefully fixed soon ;) | |
b68b7ab1 | 485 | |
d1a15766 T |
486 | =item hex |
487 | ||
43cde5e1 | 488 | Override the built-in hex() method with a version that can handle big |
d1a15766 T |
489 | integers. Note that under Perl v5.9.4 or ealier, this will be global |
490 | and cannot be disabled with "no bigint;". | |
491 | ||
492 | =item oct | |
493 | ||
43cde5e1 | 494 | Override the built-in oct() method with a version that can handle big |
c4a6f826 | 495 | integers. Note that under Perl v5.9.4 or earlier, this will be global |
d1a15766 T |
496 | and cannot be disabled with "no bigint;". |
497 | ||
b68b7ab1 T |
498 | =item v or version |
499 | ||
500 | This prints out the name and version of all modules used and then exits. | |
501 | ||
502 | perl -Mbigrat=v | |
503 | ||
95a2d02c T |
504 | =back |
505 | ||
d1a15766 T |
506 | =head1 CAVAETS |
507 | ||
508 | =over 2 | |
509 | ||
510 | =item in_effect() | |
511 | ||
512 | This method only works on Perl v5.9.4 or later. | |
513 | ||
514 | =item hex()/oct() | |
515 | ||
516 | C<bigint> overrides these routines with versions that can also handle | |
517 | big integer values. Under Perl prior to version v5.9.4, however, this | |
518 | will not happen unless you specifically ask for it with the two | |
519 | import tags "hex" and "oct" - and then it will be global and cannot be | |
520 | disabled inside a scope with "no bigint": | |
521 | ||
522 | use bigint qw/hex oct/; | |
523 | ||
524 | print hex("0x1234567890123456"); | |
525 | { | |
526 | no bigint; | |
527 | print hex("0x1234567890123456"); | |
528 | } | |
529 | ||
530 | The second call to hex() will warn about a non-portable constant. | |
531 | ||
532 | Compare this to: | |
533 | ||
534 | use bigint; | |
535 | ||
536 | # will warn only under Perl older than v5.9.4 | |
537 | print hex("0x1234567890123456"); | |
538 | ||
539 | =back | |
540 | ||
126f3c5f | 541 | =head1 EXAMPLES |
bcb1dae1 | 542 | |
126f3c5f JH |
543 | perl -Mbigrat -le 'print sqrt(33)' |
544 | perl -Mbigrat -le 'print 2*255' | |
545 | perl -Mbigrat -le 'print 4.5+2*255' | |
bcb1dae1 | 546 | perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3' |
126f3c5f | 547 | perl -Mbigrat -le 'print 12->is_odd()'; |
95a2d02c | 548 | perl -Mbignum=l,GMP -le 'print 7 ** 7777' |
126f3c5f JH |
549 | |
550 | =head1 LICENSE | |
551 | ||
552 | This program is free software; you may redistribute it and/or modify it under | |
553 | the same terms as Perl itself. | |
554 | ||
555 | =head1 SEE ALSO | |
556 | ||
557 | Especially L<bignum>. | |
558 | ||
559 | L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well | |
560 | as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. | |
561 | ||
562 | =head1 AUTHORS | |
563 | ||
95a2d02c | 564 | (C) by Tels L<http://bloodgate.com/> in early 2002 - 2007. |
126f3c5f JH |
565 | |
566 | =cut |