diff options
Diffstat (limited to 'Master/tlpkg/tlperl0/lib/Math/Pari.pm')
-rwxr-xr-x | Master/tlpkg/tlperl0/lib/Math/Pari.pm | 1195 |
1 files changed, 1195 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl0/lib/Math/Pari.pm b/Master/tlpkg/tlperl0/lib/Math/Pari.pm new file mode 100755 index 00000000000..c199898dde3 --- /dev/null +++ b/Master/tlpkg/tlperl0/lib/Math/Pari.pm @@ -0,0 +1,1195 @@ +=head1 NAME + +C<Math::Pari> - Perl interface to PARI. + +=head1 SYNOPSIS + + use Math::Pari; + $a = PARI 2; + print $a**10000; + +or + + use Math::Pari qw(Mod); + $a = Mod(3,5); + print $a**10000; + +=head1 DESCRIPTION + +This package is a Perl interface to famous library PARI for +numerical/scientific/number-theoretic calculations. It allows use of +most PARI functions as Perl functions, and (almost) seamless merging +of PARI and Perl data. In what follows we suppose prior knowledge of +what PARI is (see L<ftp://megrez.math.u-bordeaux.fr/pub/pari>, or +L<Math::libPARI>). + +=head1 EXPORTed functions + +=over 4 + +=item DEFAULT + +By default the package exports functions PARI(), PARIcol(), PARIvar(), +PARImat() and PARImat_tr() which convert their argument(s) to a +PARI object. (In fact PARI() is just an alias for C<new Math::Pari>). +The function PARI() accepts following data as its arguments + +=over 17 + +=item One integer + +Is converted to a PARI integer. + +=item One float + +Is converted to a PARI float. + +=item One string + +Is executed as a PARI expresion (so should not contain whitespace). + +=item PARI object + +Is passed unchanged. + +=item Reference to a Perl array + +Each element is converted using the same rules, PARI vector-row with these +elements is returned. + +=item Several of above + +The same as with a reference to array. + +=back + +=item Conflicts of rules in PARI() + +In deciding what rule of the above to apply the preference is given to +the uppermost choice of those available I<now>. If none matches, then +the string rule is used. So C<PARI(1)> returns integer, C<PARI(1.)> +returns float, C<PARI("1")> evaluates C<1> as a PARI expression (well, +the result is the same as C<PARI(1)>, only slower). + +Note that for Perl these data are synonimous, since Perl freely +converts between integers, float and strings. However, to PARI() only +what the argument I<is now> is important. If $v is C<1> in the Perl +world, C<PARI($v)> may convert it to an integer, float, or to the +result of evaluating the PARI program C<1> (all depending on how $v +was created and accessed in Perl). + +This is a fundamental limitation of creating an interface between two +systems, both with polymorphic objects, but with subtly different +semantic of the flavors of these objects. In reality, however, this +is rarely a problem. + +=item PARIcol(), PARImat() and PARImat_tr() + +PARIcol() behaves in the same way as PARI() unless given several +arguments. In the latter case it returns a vector-column instead of +a vector-row. + +PARImat() constructs a matrix out of the given arguments. It will work +if PARI() will construct a vector of vectors given the same arguments. +The internal vectors become columns of the matrix. PARImat_tr() +behaves similarly, but the internal vectors become rows of the matrix. + +Since PARI matrices are similar to vector-rows of vector-columns, +PARImat() is quickier, but PARImat_tr() better corresponds to the PARI +input and output forms of matrices: + + print PARImat [[1,2], [3,4]]; # prints [1,3;2,4] + print PARImat_tr [[1,2], [3,4]]; # prints [1,2;3,4] + +=item C<use> with arguments + +If arguments are specified in the C<use Math::Pari> directive, the +PARI functions appearing as arguments are exported in the caller +context. In this case the function PARI() and friends is not exported, +so if you need them, you should include them into export list +explicitely, or include C<:DEFAULT> tag: + + use Math::Pari qw(factorint PARI); + use Math::Pari qw(:DEFAULT factorint); + +or simply do it in two steps + + use Math::Pari; + use Math::Pari 'factorint'; + +The other tags recognized are C<:PARI>, C<:all>, C<prec=NUMBER>, +number tags (e.g., C<:4>), overloaded constants tags (C<:int>, +C<:float>, C<:hex>) and section names tags. The number tags export +functions from the PARI library from the given class (except for +C<:PARI>, which exports all of the classes). Tag C<:all> exports all of the +exportable symbols and C<:PARI>. + +Giving C<?> command to C<gp> (B<PARI> calculator) lists the following classes: + + 1: Standard monadic or dyadic OPERATORS + 2: CONVERSIONS and similar elementary functions + 3: TRANSCENDENTAL functions + 4: NUMBER THEORETICAL functions + 5: Functions related to ELLIPTIC CURVES + 6: Functions related to general NUMBER FIELDS + 7: POLYNOMIALS and power series + 8: Vectors, matrices, LINEAR ALGEBRA and sets + 9: SUMS, products, integrals and similar functions + 10: GRAPHIC functions + 11: PROGRAMMING under GP + +One can use section names instead of number tags. Recognized names are + + :standard :conversions :transcendental :number :elliptic + :fields :polynomials :vectors :sums :graphic :programming + +One can get the list of all of the functions accessible by C<Math::Pari>, +or the accessible functions from the given section using listPari() function. + +Starting from version 5.005 of Perl, three constant-overload tags are +supported: C<:int>, C<:float>, C<:hex>. If used, all the +integer/float/hex-or-octal-or-binary literals in Perl will be automatically +converted to became PARI objects. For example, + + use Math::Pari ':int'; + print 2**1000; + +is equivalent to + + print PARI(2)**PARI(1000); + +(The support for this Perl feature is buggy before the Perl version 5.005_57 - +unless Perl uses mymalloc options; you can check for this with C<perl +-V:usemymalloc>.) Note also that (at least with some versions of Perl) +one should enable C<':float'> for conversion of long integer literals +(I<Perl> may consider them as floats, since they won't fit into Perl +integers); note that it is PARI which determines which PARI subtype is +assigned to each such literal: + + use Math::Pari ':float', 'type_name'; + print type_name 22222222222222222222222; + +prints C<t_INT>. + +=back + +=head1 Available functions + +=head2 Directly accessible from Perl + +This package supports I<all> the functions from the PARI library with +a I<signature> which can be recognized by Math::Pari. This means that +when you update the PARI library, the newly added functions will we +available without any change to this package; only a recompile is +needed. In fact no recompile will be needed if you link libPARI +dynamically (you need to modify the F<Makefile> manually to do +this). + +You can "reach" unsupported functions via going directly to PARI +parser using the string flavor of PARI() function, as in + + 3 + PARI('O(x^17)'); + +For some "unreachable" functions there is a special wrapper functions, +such as C<O(variable,power)>). + +The following functions are specific to GP calculator, thus are not +available to Math::Pari in any way: + + default error extern input print print1 printp printp1 + printtex quit read system whatnow write write1 writetex + +whatnow() function is useless, since Math::Pari does not support the +"compatibility" mode (with older PARI library). The functionality of +print(), write() and variants is available via automatic string +translation, and pari_print() function and its variants (see L<Printout functions>). + +default() is the only important function with functionality not +supported by the current interface. Note however, that three most +important default() actions are supported by allocatemem(), +setprimelimit(), setprecision() and setseriesprecision() functions. +(When called without arguments, these functions return the current +values.) + +allocatemem($bytes) should not be called from inside Math::Pari +functions (such as forprimes()). + +=head2 Arguments + +Arguments to PARI functions are automatically converted to C<long> or +a PARI object depending on the signature of the actual library function. +The arguments are I<forced> into the given type, so even if C<gp> +rejects your code similar to + + func(2.5); # func() takes a long in C + +arguing that a particular argument should be of C<type T_INT> (i.e., a +Pari integer), the corresponding code will work in C<Math::Pari>, +since 2.5 is silently converted to C<long>, per the function +signature. + +=head2 Return values + +PARI functions return a PARI object or a Perl's integer depending on +what the actual library function returns. + +=head2 Additional functions + +Some PARI functions are available in C<gp> (i.e., in C<PARI> +calculator) via infix notation only. In C<Math::Pari> these functions +are available in functional notations too. Some other convenience +functions are also made available. + +=over 5 + +=item Infix, prefix and postfix operations + +are available under names + + gneg, gadd, gsub, gmul, gdiv, gdivent, gmod, gpui, + gle, gge, glt, ggt, geq, gne, gegal, gor, gand, + gcmp, gcmp0, gcmp1, gcmp_1. + +C<gdivent> means euclidean quotient, C<gpui> is power, C<gegal> checks +whether two objects are equal, C<gcmp> is applicable to two real +numbers only, C<gcmp0>, C<gcmp1>, C<gcmp_1> compare with 0, 1 and -1 +correspondingly (see PARI user manual for details, or +L<Math::libPARI>). Note that all these functions are more readily +available via operator overloading, so instead of + + gadd(gneg($x), $y) + +one can write + + -$x+$y + +(as far as overloading may be triggered, see L<overload>, so we assume +that at least one of $x or $y is a PARI object). + +=item Conversion functions + + pari2iv, pari2nv, pari2num, pari2pv, pari2bool + +convert a PARI object to an integer, float, integer/float (whatever is +better), string, and a boolean value correspondingly. Most the time +you do not need these functions due to automatic conversions. + +=item Printout functions + + pari_print, pari_pprint, pari_texprint + +perform the same conversions to strings as their PARI counterparts, +but do not print the result. The difference of pari_print() with +pari2pv() is the number of significant digits they output, and +whitespace in the output. pari2pv(), which is intended for +"computer-readable strings", outputs as many digits as is supported by +the current precision of the number; while pari_print(), which targets +human-readable strings, takes into account the currently specified +output precision too. + +=item Constant functions + +Some mathematical constants appear as function without arguments in +PARI. These functions are available in Math::Pari too. If you export +them as in + + use Math::Pari qw(:DEFAULT Pi I Euler); + +they can be used as barewords in your program: + + $x = Pi ** Euler; + +=item Low-level functions + +For convenience of low-level PARI programmers some low-level functions +are made available as well (all except type_name() and changevalue() +are not exportable): + + typ($x) + lg($x) + lgef($x) + lgefint($x) + longword($x, $n) + type_name($x) + changevalue($name,$newvalue) + +Here longword($x,$n) returns C<$n>-th word in the memory +representation of $x (including non-code words). type_name() differs +from the PARI function type(): type() returns a PARI object, while +type_name() returns a Perl string. (PARI objects of string type +behave very non-intuitive w.r.t. string comparison functions; remember +that they are compared using lex() to I<the results of evaluation> of +other argument of comparison!) + +The function listPari($number) outputs a list of names of PARI +functions in the section $number. Use listPari(-1) to get the list +across all of the sections. + +=item Uncompatible functions + + O + +Since implementing C<O(7**6)> would be very tedious, we provide a +two-argument form C<O(7,6)> instead (meaning the same as C<O(7^6)> in +PARI). Note that with polynomials there is no problem like this one, +both C<O($x,6)> and C<O($x**6)> work. + + ifact(n) + +integer factorial functions, available from C<gp> as C<n!>. + +=back + +=head2 Looping functions + +PARI has a big collection of functions which loops over some set. +Such a function takes two I<special> arguments: loop variable, and the +code to execute in the loop. + +The code can be either a string (which contains PARI code to execute - +thus should not contain whitespace), or a Perl code reference. The +loop variable can be a string giving the name of PARI variable (as in + + fordiv(28, 'j', 'a=a+j+j^2'); + +or + + $j= 'j'; + fordiv(28, $j, 'a=a+j+j^2'); + +), a PARI monomial (as in + + $j = PARI 'j'; + fordiv(28, $j, sub { $a += $j + $j**2 }); + +), or a "delayed Math::Pari variable" (as in + + $j = PARIvar 'j'; + fordiv(28, $j, 'a=a+j+j^2'); + +). If none of these applies, as in + + my $j; # Have this in a separate statement + fordiv(28, $j, sub { $a += $j + $j**2 }); + +then during the execution of the C<sub>, Math::Pari would autogenerate +a PARI variable, and would put its value in $j; this value of $j is +temporary only, the old contents of $j is restored when fordiv() returns. + +Note that since you have no control over this name, you will not be +able to use this variable from your PARI code; e.g., + + $j = 7.8; + fordiv(28, $j, 'a=a+j+j^2'); + +will not make C<j> mirror $j (unless you explicitely set up C<j> to be +a no-argument PARI function mirroring $j, see L<"Accessing Perl functions from PARI code">). + +B<Caveats>. There are 2 flavors of the "code" arguments +(string/C<sub>), and 4 types of the "variable" arguments +(string/monomial/C<PARIvar>/other). However, not all 8 combinations +make sense. As we already explained, an "other" variable cannot work +with a "string" code. + +B<Useless musing alert! Do not read the rest of this section!> Do not +use "string" variables with C<sub> code, and do not ask I<why>! + +Additionally, the following code will not do what you expect + + $x = 0; + $j = PARI 'j'; + fordiv(28, 'j', sub { $x += $j } ); # Use $j as a loop variable! + +since the PARI function C<fordiv> I<localizes> the PARI variable C<j> +inside the loop, but $j will still reference the old value; the old +value is a monomial, not the index of the loop (which is an integer +each time C<sub> is called). The simplest workaround is not to use +the above syntax (i.e., not mixing literal loop variable with Perl +loop code, just using $j as the second argument to C<fordiv> is +enough): + + $x = 0; + $j = PARI 'j'; + fordiv(28, $j, sub { $x += $j } ); + +Alternately, one can make a I<delayed> variable $j which will always +reference the same thing C<j> references in PARI I<now> by using +C<PARIvar> constructor + + $x = 0; + $j = PARIvar 'j'; + fordiv(28, 'j', sub { $x += $j } ); + +(This problem is similar to + + $ref = \$_; # $$ref is going to be old value even after + # localizing $_ in Perl's grep/map + +not accessing localized values of $_ in the plain Perl.) + +Another possible quirk is that + + fordiv(28, my $j, sub { $a += $j + $j**2 }); + +will not work too - by a different reason. C<my> declarations change +the I<meaning> of $j only I<after> the end of the current statement; +thus $j inside C<sub> will access a I<different> variable $j +(typically a non-lexical, global variable $j) than one you declared on this line. + +=head2 Accessing Perl functions from PARI code + +Use the same name inside PARI code: + + sub counter { $i += shift; } + $i = 145; + PARI 'k=5' ; + fordiv(28, 'j', 'k=k+counter(j)'); + print PARI('k'), "\n"; + +prints + + 984 + +Due to a difference in the semantic of +variable-number-of-parameters-functions between PARI and Perl, if the +Perl subroutine takes a variable number of arguments (via C<@> in the +prototype or a missing prototype), up to 6 arguments are supported +when this function is called from PARI. If called from PARI with +fewer arguments, the rest of arguments will be set to be integers C<PARI 0>. + +Note also that no direct import of Perl variables is available yet +(but you can write a function wrapper for this): + + sub getv () {$v} + +There is an unsupported (and undocumented ;-) function for explicitely +importing Perl functions into PARI, possibly with a different name, +and possibly with explicitely specifying number of arguments. + +=head1 PARI objects + +Functions from PARI library may take as arguments and/or return values +the objects of C type C<GEN>. In Perl these data are encapsulated into +special kind of Perl variables: PARI objects. You can check for a +variable C<$obj> to be a PARI object using + + ref $obj and $obj->isa('Math::Pari'); + +Most the time you do not need this due to automatic conversions and overloading. + +=head1 PARI monomials and Perl barewords + +If very lazy, one can code in Perl the same way one does it in PARI. +Variables in PARI are denoted by barewords, as in C<x>, and in the +default configuration (no warnings, no strict) Perl allows the same - +up to some extent. Do not do this, since there are many surprising problems. + +Some bareletters denote Perl operators, like C<q>, C<x>, C<y>, +C<s>. This can lead to errors in Perl parsing your expression. E.g., + + print sin(tan(t))-tan(sin(t))-asin(atan(t))+atan(asin(t)); + +may parse OK after C<use Math::Pari qw(sin tan asin atan)>. Why? + +After importing, the word C<sin> will denote the PARI function sin(), +not Perl operator sin(). The difference is subtle: the PARI function +I<implicitly> forces its arguments to be converted PARI objects; it +gets C<'t'> as the argument, which is a string, thus is converted to +what C<t> denotes in PARI - a monomial. While the Perl operator sin() +grants overloading (i.e., it will call PARI function sin() if the +argument is a PARI object), it does not I<force> its argument; given +C<'t'> as argument, it converts it to what sin() understands, a float +(producing C<0.>), so will give C<0.> as the answer. + +However + + print sin(tan(y))-tan(sin(y))-asin(atan(y))+atan(asin(y)); + +would not compile. You should avoid lower-case barewords used as PARI +variables, e.g., do + + $y = PARI 'y'; + print sin(tan($y))-tan(sin($y))-asin(atan($y))+atan(asin($y)); + +to get + + -1/18*y^9+26/4725*y^11-41/1296*y^13+328721/16372125*y^15+O(y^16) + +(BTW, it is a very good exercise to get the leading term by hand). + +Well, the same advice again: do not use barewords anywhere in your program! + +=head1 Overloading and automatic conversion + +Whenever an arithmetic operation includes at least one PARI object, +the other arguments are converted to a PARI object and the corresponding +PARI library functions is used to implement the operation. Currently +the following arithmetic operations are overloaded: + + unary - + + - * / % ** abs cos sin exp log sqrt + << >> + <= == => < > != <=> + le eq ge lt gt ne cmp + | & ^ ~ + +Numeric comparison operations are converted to C<gcmp> and friends, string +comparisons compare in lexicographical order using C<lex>. + +Additionally, whenever a PARI object appears in a situation that requires integer, +numeric, boolean or string data, it is converted to the corresponding +type. Boolean conversion is subject to usual PARI pitfalls related to +imprecise zeros (see documentation of C<gcmp0> in PARI reference). + +For details on overloading, see L<overload>. + +Note that a check for equality is subject to same pitfalls as in PARI +due to imprecise values. PARI may also refuse to compare data of +different types for equality if it thinks this may lead to +counterintuitive results. + +Note also that in PARI the numeric ordering is not defined for some +types of PARI objects. For string comparison operations we use +PARI-lexicographical ordering. + +=head1 PREREQUISITES + +=head2 Perl + +In the versions of perl earlier than 5.003 overloading used a +different interface, so you may need to convert C<use overload> line +to C<%OVERLOAD>, or, better, upgrade. + +=head2 PARI + +Starting from version 2.0, this module comes without a PARI library included. + +For the source of PARI library see +L<ftp://megrez.math.u-bordeaux.fr/pub/pari>. + +=head1 Perl vs. PARI: different syntax + +Note that the PARI notations should be used in the string arguments to +PARI() function, while the Perl notations should be used otherwise. + +=over 4 + +=item C<^> + +Power is denoted by C<**> in Perl. + +=item C<\> and C<\/> + +There are no such operators in Perl, use the word forms +C<gdivent(x,y)> and C<gdivround(x,y)> instead. + +=item C<~> + +There is no postfix C<~> Perl operator. Use mattranspose() instead. + +=item C<'> + +There is no postfix C<'> Perl operator. Use deriv() instead. + +=item C<!> + +There is no postfix C<!> Perl operator. Use factorial()/ifact() instead +(returning a real or an integer correspondingly). + +=item big integers + +Perl converts big I<literal> integers to doubles if they could not be +put into B<C> integers (the particular flavor can be found in the +output of C<perl -V> in newer version of Perl, look for +C<ivtype>/C<ivsize>). If you want to input such an integer, use + + while ($x < PARI('12345678901234567890')) ... + +instead of + + while ($x < 12345678901234567890) ... + +Why? Because conversion to double leads to precision loss (typically +above 1e15, see L<perlnumber>), and you will get something like +12345678901234567168 otherwise. + +Starting from version 5.005 of Perl, if the tag C<:int> is used on the +'use Math::Pari' line, all of the integer literals in Perl will be +automatically converted to became PARI objects. E.g., + + use Math::Pari ':int'; + print 2**1000; + +is equivalent to + + print PARI(2)**PARI(1000); + +Similarly, large integer literals do not lose precision. + +This directive is lexically scoped. There is a similar tag C<:hex> +which affects hexadecimal, octal and binary constants. One may +also need to use tag C<:float> for auto-conversion of large integer literals +which Perl considers as floating point literals (see L<C<use> with arguments> +for details). + +=item doubles + +Doubles in Perl are typically of precision approximately 15 digits +(see L<perlnumber>). When you use them as arguments to PARI +functions, they are converted to PARI real variables, and due to +intermediate 15-digits-to-binary conversion of Perl variables the +result may be different than with the PARI many-digits-to-binary +conversion. E.g., C<PARI(0.01)> and C<PARI('0.01')> differ at 19-th +place, as + + setprecision(38); + print pari_print(0.01), "\n", + pari_print('0.01'), "\n"; + +shows. + +Note that setprecision() changes the output format of pari_print() and +friends, as well as the default internal precision. The generic +PARI===>string conversion does not take into account the output +format, thus + + setprecision(38); + print PARI(0.01), "\n", + PARI('0.01'), "\n", + pari_print(0.01), "\n"; + +will print all the lines with different number of digits after the +point: the first one with 22, since the double 0.01 was converted to a +low-precision PARI object, the second one with 41, since internal form +for precision 38 requires that many digits for representation, and the +last one with 39 to have 38 significant digits. + +Starting from version 5.005 of Perl, if the tag C<:float> is used on +the C<use Math::Pari> line, all the float literals in Perl will be +automatically converted to became PARI objects. E.g., + + use Math::Pari ':float'; + print atan(1.); + +is equivalent to + + print atan(PARI('1.')); + +Similarly, large float literals do not lose precision. + +This directive is lexically scoped. + +=item array base + +Arrays are 1-based in PARI, are 0-based in Perl. So while array +access is possible in Perl, you need to use different indices: + + $nf = PARI 'nf'; # assume that PARI variable nf contains a number field + $a = PARI('nf[7]'); + $b = $nf->[6]; + +Now $a and $b contain the same value. + +=item matrices + +Note that C<PARImat([[...],...,[...])> constructor creates a matrix +with specified columns, while in PARI the command C<[1,2,3;4,5,6]> +creates a matrix with specified rows. Use a convenience function +PARImat_tr() which will transpose a matrix created by PARImat() to use +the same order of elements as in PARI. + +=item builtin perl functions + +Some PARI functions, like C<length> and C<eval>, are Perl +(semi-)reserved words. To reach these functions, one should either +import them: + + use Math::Pari qw(length eval); + +or call them with prefix (like C<&length>) or the full name (like +C<Math::Pari::length>). + +=back + +=head1 High-resolution graphics + +If you have Term::Gnuplot Perl module installed, you may use high-resolution +graphic primitives of B<PARI>. Before the usage you need to establish +a link between Math::Pari and Term::Gnuplot by calling link_gnuplot(). +You can change the output filehandle by calling set_plot_fh(), and +output terminal by calling plotterm(), as in + + use Math::Pari qw(:graphic asin); + + open FH, '>out.tex' or die; + link_gnuplot(); # automatically loads Term::Gnuplot + set_plot_fh(\*FH); + plotterm('emtex'); + ploth($x, .5, .999, sub {asin $x}); + close FH or die; + +=head1 libPARI documentation + +libPARI documentation is included, see L<Math::libPARI>. It is converted +from Chapter 3 of B<PARI/GP> documentation by the F<gphelp> script of GP/PARI. + +=head1 ENVIRONMENT + +No environment variables are used. + +=head1 BUGS + +=over 5 + +=item * + +A few of PARI functions are available indirectly only. + +=item * + +Using overloading constants with the Perl versions below 5.005_57 could lead to +segfaults (at least without C<-D usemymalloc>), as in: + + use Math::Pari ':int'; + for ( $i = 0; $i < 10 ; $i++ ) { print "$i\n" } + +=item * + +It may be possible that conversion of a Perl value which has both the +integer slot and the floating slot set may create a PARI integer, even +if the actual value is not an integer. + +=item * + +problems with refcounting of array elements and Mod(). + +Workaround: make the modulus live longer than the result of Mod(). +Until Perl version C<5.6.1>, one should exercise a special care so +that the modulus goes out of scope on a different statement than the +result: + + { my $modulus = 125; + { my $res = Mod(34, $modulus); + print $res; + } + $fake = 1; # A (fake) statement here is required + } + +Here $res is destructed before the C<$fake = 1> statement, $modulus is +destructed before the first statement after the provided block. +However, if you remove the C<$fake = 1> statement, both these +variables are destructed on the first statement after the provided +block (and in a wrong order!). + +In C<5.6.1> declaring $modulus before $res is all that is needed to +circumvent the same problem: + + { my $modulus = 125; + my $res = Mod(34, $modulus); + print $res; + } # destruction will happen in a correct order. + +Access to array elements may result in similar problems. Hard to fix +since in PARI the data is not refcounted. + +=item * + +Legacy implementations of dynalinking require the code of DLL to be +compiled to be "position independent" code (PIC). This slows down the +execution, while allowing sharing the loaded copy of the DLL between +different processes. [On contemeporary architectures the same effect +is allowed without the position-independent hack.] + +Currently, PARI assembler files are not position-independent. When +compiled for the dynamic linking on legacy systems, this creates a DLL +which cannot be shared between processes. Some legacy systems are +reported to recognize this situation, and load the DLL as a non-shared +module. However, there may be systems (are there?) on which this can +cause some "problems". + +Summary: if the dynaloading on your system requires some kind of C<-fPIC> flag, using "assembler" compiles (anything but C<machine=none>) *may* force you to do a static build (i.e., creation of a custom Perl executable with + + perl Makefile.PL static + make perl + make test_static + +). + +=back + +=head1 INITIALIZATION + +When Math::Pari is loaded, it examines variables $Math::Pari::initmem +and $Math::Pari::initprimes. They specify up to which number the +initial list of primes should be precalculated, and how large should +be the arena for PARI calculations (in bytes). (These values have +safe defaults.) + +Since setting these values before loading requires either a C<BEGIN> +block, or postponing the loading (C<use> vs. C<require>), it may be +more convenient to set them via Math::PariInit: + + use Math::PariInit qw( primes=12000000 stack=1e8 ); + +C<use Math::PariInit> also accepts arbitrary Math::Pari import directives, +see L<Math::PariInit>. + +These values may be changed at runtime too, via allocatemem() and +setprimelimit(), with performance penalties for recalculation/reallocation. + +=head1 AUTHOR + +Ilya Zakharevich, I<ilyaz@cpan.org> + +=cut + +# $Id: Pari.pm,v 1.3 1994/11/25 23:40:52 ilya Exp ilya $ +package Math::Pari::Arr; + +#sub TIEARRAY { $_[0] } +sub STORE { die "Storing into array elements unsupported" } + +package Math::Pari; + +require Exporter; +require DynaLoader; +#use autouse Carp => 'croak'; + +@ISA = qw(Exporter DynaLoader); +@Math::Pari::Ep::ISA = qw(Math::Pari); + +# Items to export into callers namespace by default +# (move infrequently used names to @EXPORT_OK below) + +@EXPORT = qw( +PARI PARIcol PARImat PARIvar PARImat_tr +); + +# Other items we are prepared to export if requested (may be extended during +# ->import. ) +@EXPORT_OK = qw( + sv2pari sv2parimat pari2iv pari2nv pari2num pari2pv pari2bool loadPari _bool + listPari pari_print pari_pprint pari_texprint O ifact gdivent gdivround + changevalue set_plot_fh link_gnuplot setprecision setseriesprecision + setprimelimit allocatemem type_name pari2num_ +); + +use subs qw( + _gneg + _gadd + _gsub + _gmul + _gdiv + _gmod + _gpui + _gle + _gge + _glt + _ggt + _geq + _gne + _gcmp + _lex + _2bool + pari2pv + pari2num + pari2num_ + _abs + _cos + _sin + _exp + _log + _sqrt + _gbitand + _gbitor + _gbitxor + _gbitneg + _to_int + _gbitshiftr + _gbitshiftl +); # Otherwise overload->import would complain... + +my $two; + +sub _shiftl { + my ($left,$right) = (shift,shift); + ($left,$right) = ($right, $left) if shift; + $left * $two**$right; +} + +sub _shiftr { + my ($left,$right) = (shift,shift); + ($left,$right) = ($right, $left) if shift; + floor($left / $two**$right); +} + +$initmem ||= 4000000; # How much memory for the stack +$initprimes ||= 500000; # Calculate primes up to this number + +$VERSION = '2.010801'; + +my $true = 1; +# Propagate sv_true, sv_false to SvIOK: +my $dummy = pack 'ii', $true == 1, $true == 0; + +bootstrap Math::Pari; + +use overload qw( + neg _gneg + + _gadd + - _gsub + * _gmul + / _gdiv + % _gmod + ** _gpui + <= _gle + >= _gge + < _glt + > _ggt + == _geq + != _gne + <=> _gcmp + cmp _lex + bool _2bool + "" pari2pv + 0+ pari2num_ + abs _abs + cos _cos + sin _sin + exp _exp + log _log + sqrt _sqrt + int _to_int +); + +if (pari_version_exp() >= 2000018) { + 'overload'->import( qw( + | _gbitor + & _gbitand + ^ _gbitxor + ~ _gbitneg + ) ); +} + +if (pari_version_exp() >= 2002001) { + 'overload'->import( qw( << _gbitshiftl ) ); +} else { + 'overload'->import( qw( << _shiftl ) ); +} +if (pari_version_exp() >= 2002001 && pari_version_exp() <= 2002007) { + 'overload'->import( qw( >> _gbitshiftr ) ); +} else { + 'overload'->import( qw( >> _shiftr ) ); +} + +sub AUTOLOAD { + $AUTOLOAD =~ /^(?:Math::Pari::)?(.*)/; + # warn "Autoloading $1...\n"; + # exit 4 if $1 eq 'loadPari'; + my $cv = loadPari($1); + +# goto &$cv; +# goto &$AUTOLOAD; +# &$cv; + &$1; +# &$AUTOLOAD; +} + +# Needed this guy to circumwent autoloading while no XS definition + +#### sub DESTROY {} + + +# sub AUTOLOAD { +# if ((caller(0))[4]) { +# $AutoLoader::AUTOLOAD = $AUTOLOAD; +# goto &AutoLoader::AUTOLOAD; +# } +# local($constname); +# ($constname = $AUTOLOAD) =~ s/.*:://; +# $val = constant($constname, @_ ? $_[0] : 0); +# if ($! != 0) { +# if ($! =~ /Invalid/) { +# $AutoLoader::AUTOLOAD = $AUTOLOAD; +# goto &AutoLoader::AUTOLOAD; +# } +# else { +# ($pack,$file,$line) = caller; +# die "Your vendor has not defined Math::Pari macro $constname, used at $file line $line. +# "; +# } +# } +# eval "sub $AUTOLOAD { $val }"; +# goto &$AUTOLOAD; +# } + +# Preloaded methods go here. Autoload methods go after __END__, and are +# processed by the autosplit program. + +sub new { + shift; + if (@_>1) {my(@t)=@_;return sv2pari(\@t)} + return sv2pari(shift); +} + +###sub PARI {new Math::Pari @_} + +%names = qw( + 1 standard + 2 conversions + 3 transcendental + 4 number + 5 elliptic + 6 fields + 7 polynomials + 8 vectors + 9 sums + 10 graphic + 11 programming + ); +@sections{values %names} = keys %names; + +@converted{split /,\s+/, qq(buchimag, buchreal, + buchgen, buchgenforcefu, buchgenfu, buchinit, buchinitforcefu, buchinitfu, + plotstring, addhelp, kill)} = (1) x 100; + +# Now even tested... +sub _cvt { PARI(shift) } +sub _hex_cvt { + my $in = shift; + my $mult = PARI(1); + my $ret = 0; + my $shift = 1<<(4*7); + + $in =~ s/^0([xb])?// or die; + my $hex = $1; + if ($hex and $1 eq 'b') { + my $b = '0' x (15 * length($in) % 16) . $in; + $hex = ''; + while ($b) { + my $s = substr $b, 0, 16; + substr($b, 0, 16) = ''; + $hex .= unpack 'H4', pack 'B16', $s; + } + $in = $hex; + } + $shift = 1<<(3*7) unless $hex; + while ($in =~ s/([a-fA-F\d]{1,7})$//) { + # In 5.6.0 hex() can return a floating number: + my $part = int($hex ? hex $1 : oct $1); + + $ret += $part * $mult; + $mult *= $shift; + } + die "Cannot hex '$in'" if length $in; + return $ret; +} +%overloaded_const = ( 'int' => \&_cvt, float => \&_cvt, 'hex' => \&_hex_cvt); +%overloaded_const_word + = ( 'int' => 'integer', float => 'float', 'hex' => 'binary'); + +sub import { + my $p=shift; + my @consts; # Need to do it outside any block! + @_ = map { + if (/^:(?!DEFAULT)(.*)/) { + my $tag = $1; + my $sect = $tag; + my @pre; + $tag = -1, @pre = (@EXPORT_OK,@EXPORT) if ($tag eq 'all'); + $tag = -1 if ($tag eq 'PARI'); + $tag = $sections{$tag} if $tag !~ /^-?\d+$/ and exists $sections{$tag}; + push @pre, 'link_gnuplot', 'set_plot_fh' if $tag eq 10; + if ($tag =~ /^prec=(\d+)$/) { + setprecision($1); + (); + } elsif ($tag =~ /^(int|hex|float)$/) { + die "Overloaded constants are not supported in this version of Perl" + if $] < 5.004_69; + push @const, $overloaded_const_word{$tag} => $overloaded_const{$tag}; + # print "Constants: $overloaded_const_word{$tag} => $overloaded_const{$tag} \n"; + (); + } elsif (defined $tag and $tag =~ /^-?\d+$/) { + (@pre, listPari($tag)); + } else { + die "Unknown section '$sect' specified"; + } + } else { + ($_); + } + } @_; + + overload::constant(splice @const, 0, 2) while @const; + + # print "EXPORT_OK: @EXPORT_OK\n"; + push @EXPORT_OK, + grep( ($_ ne ':DEFAULT' + and not $export_ok{$_}++ + and (eval {loadPari($_), 1} or warn $@), !$@) , + @_); + # Invalidate Exporter cache, so that new %EXPORT_OK is noticed: + undef %EXPORT; + # print "EXPORT_OK: @EXPORT_OK\n"; + &Exporter::export($p,(caller(0))[0],@_); +} + +sub _can { # Without taking into account inheritance... + my ($obj, $meth) = (shift, shift); + return \&$meth if defined &$meth; + return \&$meth if eval {loadPari($meth), 1}; + return; +} + +sub can { + my ($obj, $meth) = (@_); + my $f = $obj->SUPER::can($meth); + return $f if defined $f; + # There is no "usual" way to get the function; try loadPari() + $f = eval { loadPari($meth) }; + return $f if defined $f; + return; +} + +sub O ($;$) { + return PARI("O($_[0]^$_[1])") if @_ == 2; + return PARI("O($_[0])") if typ($_[0]) == 10; # Poly + Carp::croak("O(number**power) not implemented, use O(number,power) instead"); +} + +sub PARImat_tr {mattranspose(PARImat(@_))} +#sub string ($$) { +# PARI (qq'string($_[0],"$_[1]")'); +#} + +sub installPerlFunction {my @a=@_; $a[0] = \&{$a[0]}; installPerlFunctionCV(@a)} + +my $name; + +for $name (keys %converted) { + push @EXPORT_OK, $name; + next if defined &$name; + # string needs to format numbers to 8.3... + if ($name eq 'addhelp' or $name eq 'plotstring') { + *$name = sub { PARI ( qq($name($_[0],"$_[1]")) ) } + } else { + *$name = sub { local $"=','; PARI("$name(@_)") } + } +} + +@export_ok{@EXPORT_OK,@EXPORT} = (1) x (@EXPORT_OK + @EXPORT); + +sub link_gnuplot { + eval 'use Term::Gnuplot 0.56; 1' or die; + int_set_term_ftable(Term::Gnuplot::get_term_ftable()); +} + +sub set_plot_fh { + eval 'use Term::Gnuplot 0.4; 1' or die; + Term::Gnuplot::set_gnuplot_fh(@_); +} + +PARI_DEBUG_set($ENV{MATHPARI_DEBUG} || 0); +$two = PARI(2); + +1; +__END__ |