API reference
LibPARI exposes PARI/GP to Julia through two layers: a large machine-generated binding layer, and a compact hand-written core. This page documents both.
The generated bindings — LibPARI.PARI
The LibPARI.PARI submodule holds nearly 1200 bindings, one per eligible PARI/GP function, generated directly from PARI's own machine-readable function database (pari.desc). Each binding:
- keeps PARI's function name (e.g.
LibPARI.PARI.nextprime,LibPARI.PARI.factorial,LibPARI.PARI.isprime); - carries PARI's own
Helptext as its docstring — query it with?at the REPL, e.g.?LibPARI.PARI.nextprime; - takes and returns
Genvalues (or the scalar Julia type the function's prototype calls for), and is type-stable; - routes through the same safe, leak-free, thread-safe call boundary as the hand-written API.
A few prototype conventions are worth knowing:
- Precision arguments are supplied automatically; pass a
preckeyword to override the working precision. - Optional arguments are exposed as keyword arguments with PARI's declared defaults.
- Output arguments are returned alongside the primary result as a tuple.
- Functions taking a GP closure argument are not generated — reach them through
gp_evalinstead.
Because the binding layer is generated, it is not enumerated symbol-by-symbol here; PARI's own function reference is the authoritative index of what each function computes. The rest of this page documents the hand-written core in full.
Hand-written core
LibPARI.LibPARILibPARI.LibraryStateLibPARI.PariErrLibPARI.PariTypeBase.ComplexBase.ComplexBase.GMP.BigIntBase.MPFR.BigFloatBase.MatrixBase.RationalBase.RationalBase.VectorCore.Float32Core.Float64Core.TypeLibPARI.ConversionErrorLibPARI.GenLibPARI.GenLibPARI.GenLibPARI.GenLibPARI.GenArgLibPARI.PariConvertibleLibPARI.PariErrorLibPARI.PariObjectBase.denominatorBase.factorialBase.gcdBase.gcdxBase.getindexBase.getindexBase.invmodBase.lengthBase.numeratorBase.powermodBase.sizeLibPARI.ModLibPARI.__init__LibPARI._close_libpari!LibPARI._configured_stack_sizeLibPARI._init_libpari!LibPARI._validate_parisizeLibPARI.coeffLibPARI.degreeLibPARI.factorLibPARI.factorsLibPARI.gen_convertLibPARI.gen_fromLibPARI.gentypeLibPARI.gp_evalLibPARI.is_initializedLibPARI.isprimeLibPARI.library_stateLibPARI.liftLibPARI.nextprimeLibPARI.pariLibPARI.pari_modLibPARI.polrootsLibPARI.prevprimeLibPARI.protected_callLibPARI.stack_sizeLibPARI.substLibPARI.to_symbolics
Library lifecycle
LibPARI.LibraryState — Module
Lifecycle states of the embedded PARI library.
LibraryState.T is a module-scoped enum with three values:
UNINITIALIZED—pari_inithas not (successfully) runINITIALIZED— PARI is ready; a process-exit shutdown is registeredCLOSED—pari_closehas run at process exit
LibPARI._close_libpari! — Method
Release PARI's resources by calling pari_close, but only while the library is INITIALIZED. Idempotent — a second invocation is a no-op. Registered with atexit so it runs once at process exit (REQ-INI-05).
LibPARI._configured_stack_size — Method
Return the PARI main-stack size (bytes) for this process: the value of the LIBPARI_STACK_SIZE environment variable when set, otherwise the 8 MiB default. Throw ArgumentError when the variable holds an invalid value.
LibPARI._init_libpari! — Method
Initialize the PARI library for this process.
Initializes PARI exactly once: when the library is not UNINITIALIZED this is a no-op (the guard for REQ-INI-02 / REQ-INI-06). parisize is validated first; an invalid value throws before PARI is initialized, leaving the state UNINITIALIZED (REQ-INI-07). On success the state becomes INITIALIZED, the size is recorded, and pari_close is registered to run at process exit.
Uses pari_init_opts (not plain pari_init) with INIT_SIGm cleared, so PARI leaves Julia's signal handlers intact (research.md D10).
LibPARI._validate_parisize — Method
Validate a candidate PARI main-stack size n (bytes) and return it as an Int. Throw ArgumentError when n is below the 1 MiB minimum.
LibPARI.is_initialized — Method
is_initialized() -> Bool
Return true when the PARI library has been successfully initialized in this process and not yet closed.
Examples
julia> using LibPARI
julia> LibPARI.is_initialized()
trueLibPARI.library_state — Method
library_state() -> LibPARI.LibraryState.T
Return the current lifecycle state of the PARI library as a LibraryState.T value (UNINITIALIZED, INITIALIZED, or CLOSED).
Examples
julia> using LibPARI
julia> LibPARI.library_state() === LibPARI.LibraryState.INITIALIZED
trueLibPARI.stack_size — Method
stack_size() -> Int64
Return the size, in bytes, of PARI's main stack — the value passed to pari_init for this process (the 8 MiB default, or a LIBPARI_STACK_SIZE override). Returns 0 before initialization.
Examples
julia> using LibPARI
julia> LibPARI.stack_size() isa Integer
true
julia> LibPARI.stack_size() >= 1024 * 1024
trueThe Gen value type
LibPARI.Gen — Type
mutable struct Gen <: LibPARI.PariObjectA Julia value wrapping one PARI object (a PARI GEN).
Gen is a concrete, mutable type. Each Gen owns a private clone of its PARI object in PARI's persistent storage; a garbage-collection finalizer frees that clone exactly once. Every PARI object that LibPARI exposes to Julia is a Gen.
Gen is a PariObject, not a Julia Number: one concrete Gen wraps every PARI type, matrices, strings and closures included, so a Number supertype would be a false claim (REQ-TYPE-01). The arithmetic, equality and ordering that Base's Number fallbacks used to supply are declared explicitly on Gen instead — see src/numeric.jl.
Examples
julia> using LibPARI
julia> isconcretetype(LibPARI.Gen)
trueLibPARI.PariObject — Type
abstract type PariObjectThe supertype of every PARI object LibPARI exposes to Julia.
PariObject exists so that Gen can name what it is. A Gen wraps any PARI GEN — an integer, a real, a matrix, a string, a closure — so it cannot honestly be a Julia Number (REQ-TYPE-01). Julia code that must accept a PARI object generically dispatches on PariObject.
Examples
julia> using LibPARI
julia> LibPARI.Gen <: LibPARI.PariObject
trueLibPARI.gen_from — Method
Build a Gen from producer, a function that returns a raw PARI GEN computed on the transient stack.
gen_from captures PARI's stack pointer, runs producer, clones the result into persistent storage, restores the stack pointer, and returns the Gen. This capture → produce → clone → restore discipline keeps the PARI stack leak-free (REQ-MEM-03, REQ-MEM-05); it is the pattern every generated binding (M4) will reuse.
Examples
julia> using LibPARI
julia> LibPARI.gen_from isa Function
trueLibPARI.gentype — Method
gentype(g::Gen) -> LibPARI.PariType.T
Return the PARI value type of g as a PariType.T — T_INT, T_REAL, T_POL, T_VEC, and so on.
Examples
julia> using LibPARI
julia> LibPARI.gentype isa Function
trueLibPARI.PariType — Module
Module-scoped enum of PARI's value types — the t_* type tags.
PariType.T has one value per PARI object type (T_INT, T_REAL, T_POL, T_VEC, …). Each value's integer equals PARI's own t_* constant, so a type tag read from a GEN converts directly to PariType.T. See gentype.
Error handling
LibPARI.PariErr — Module
Module-scoped enum of PARI's error categories (PARI's numerr_t).
PariErr.T has one value per PARI error kind — e_SYNTAX, e_TYPE, e_DOMAIN, e_INV, e_STACK, and so on. Each value's integer equals PARI's own error number. See gentype's sibling PariError for how it is used.
LibPARI.PariError — Type
struct PariError <: ExceptionException raised when a libpari call signals a PARI error.
PariError carries PARI's own error message and a category (a PariErr.T naming the kind of error). It is an ordinary catchable Julia exception — use try/catch.
Examples
julia> using LibPARI
julia> LibPARI.PariError <: Exception
trueLibPARI.protected_call — Method
Run producer — a function performing one or more libpari calls — inside the PARI error-trapping boundary.
On success the result of producer() is returned unchanged. If a libpari call raises a PARI error, a PariError is thrown; the PARI stack pointer is restored to its pre-call value before the exception propagates, so the library stays usable. This is the boundary every generated binding (M4) routes through.
Examples
julia> using LibPARI
julia> LibPARI.protected_call isa Function
trueThe entry point and the high-level facade
pari(x) is the entry point; the rest of this section is the deliberately small facade over the generated layer. Every facade function documents the Julia and PARI inputs it accepts, its exact return type, and how it fails.
Base.denominator — Method
denominator(g::Gen) -> Gen
The denominator of an integer or rational Gen; 1 for an integer.
Throws ArgumentError for any other PARI type — see numerator.
Base.factorial — Method
factorial(g::Gen) -> Gen
The factorial of a non-negative integer Gen, computed by PARI.
Throws ArgumentError for a negative or non-integer argument — PARI's own mpfact is not checked for a negative input, so the wrapper validates first.
Examples
julia> using LibPARI
julia> factorial(pari(20))
2432902008176640000Base.gcd — Method
gcd(a::Gen, b::Gen) -> Gen
The greatest common divisor, as PARI computes it.
Accepts an integer- or rational-valued Gen, or any PariConvertible value of those kinds, on either side; returns a Gen. Matches Base.gcd, which is defined for Integer and Rational.
Throws ArgumentError on any other PARI type. PARI answers for reals, complex numbers and polynomials too — gcd(12, 1.5) is 1 there — but those are PARI's domain, not Julia's; reach them as LibPARI.PARI.ggcd0.
Examples
julia> using LibPARI
julia> gcd(pari(12), 18)
6Base.gcdx — Method
gcdx(a::Gen, b::Gen) -> Tuple{Gen, Gen, Gen}
The extended greatest common divisor: (d, u, v) with d == u*a + v*b, in Julia's argument order.
PARI's gcdext returns [u, v, d]; this reorders it to match Base.gcdx so the result can be destructured the usual way.
Restricted to integer- and rational-valued arguments, like gcd — PARI computes a Bézout identity over the reals too, which Base.gcdx does not mean.
Examples
julia> using LibPARI
julia> d, u, v = gcdx(pari(12), pari(18));
julia> d == u * pari(12) + v * pari(18)
trueBase.invmod — Method
invmod(x::Gen, m::Gen) -> Gen
The inverse of x modulo m, matching Base.invmod.
Raises a catchable PariError when x is not invertible modulo m — PARI reports the offending common factor in its message.
Base.numerator — Method
numerator(g::Gen) -> Gen
The numerator of an integer or rational Gen.
Throws ArgumentError for any other PARI type: PARI answers denominator(x/2 + 1/3) == 1 in the polynomial domain, which is a different question from Julia's numerator.
Base.powermod — Method
powermod(x::Gen, p::Integer, m::Gen) -> Gen
x^p mod m, matching Base.powermod. A negative exponent inverts x modulo m first, and raises a PariError when it is not invertible.
LibPARI.Mod — Method
Mod(a::Gen, n::Gen) -> Gen
The class of a modulo n — PARI's Mod(a, n), a t_INTMOD.
Use lift to recover a representative as a plain integer.
Examples
julia> using LibPARI
julia> LibPARI.Mod(5, 7)
Mod(5, 7)LibPARI.coeff — Method
coeff(g::Gen, k::Integer) -> Any
The coefficient of x^k in a polynomial Gen, as a Gen.
LibPARI.degree — Method
degree(g::Gen) -> Int64
The degree of a polynomial Gen, as a Julia Int.
Raises DomainError on the zero polynomial, where PARI answers -oo: there is no Int for it, and returning a sentinel would be a trap.
LibPARI.factor — Method
factor(n::Gen) -> Gen
The factorization of a non-zero integer Gen, in PARI's own shape: a two-column t_MAT of primes and exponents.
A negative argument carries the unit -1 as its first factor, as it does in Primes.jl. Zero raises ArgumentError: it has no factorization, and PARI's own answer for it ([0 1]) does not name a prime.
See factors for the Julia shape.
LibPARI.factors — Method
factors(n::Gen) -> Vector{Pair{Gen, Gen}}
The factorization of an integer as a Vector{Pair{Gen,Gen}} of prime => exponent, in increasing order of prime.
Returns an empty vector for 1, which has no prime factors. A negative argument carries -1 => 1 first. Zero raises ArgumentError.
Examples
julia> using LibPARI
julia> LibPARI.factors(60)
3-element Vector{Pair{Gen, Gen}}:
Gen(2) => Gen(2)
Gen(3) => Gen(1)
Gen(5) => Gen(1)LibPARI.isprime — Method
isprime(n::Gen) -> Bool
Whether n is prime, as a Julia Bool.
Accepts a Gen or any PariConvertible integer. Uses PARI's isprime, which is a proof, not a probabilistic test.
Not exported: the name belongs to Primes.jl.
Examples
julia> using LibPARI
julia> LibPARI.isprime(1009)
trueLibPARI.lift — Method
lift(g::Gen) -> Gen
Lift a t_INTMOD (or t_POLMOD) to a representative in its base ring.
Examples
julia> using LibPARI
julia> LibPARI.lift(LibPARI.Mod(12, 7))
5LibPARI.nextprime — Method
nextprime(n::Gen) -> Gen
The smallest prime >= n.
PARI documents this as the next pseudoprime; for the sizes reachable here it is a proven prime.
LibPARI.pari — Method
pari(x) -> Any
Convert x to a PARI value — the entry point to LibPARI.
pari accepts the Julia types listed in PariConvertible: integers of any size, rationals, floats (including BigFloat, exactly), and complex numbers of those. A Gen is returned unchanged, so pari is cheap to apply defensively and never clones twice.
Anything else raises ConversionError naming the type.
Examples
julia> using LibPARI
julia> pari(42)
42
julia> pari(3 // 4) + 1
7/4
julia> g = pari(2)^100
1267650600228229401496703205376
julia> pari(g) === g
trueLibPARI.pari_mod — Method
pari_mod(a::Gen, n::Gen) -> Gen
a mod n, with Julia's sign convention: the result takes the sign of n.
PARI's own % does not. It always answers in [0, |n|), so PARI.gmod(7, -3) is 1 where mod(7, -3) is -2 in Julia. This wrapper corrects for that; PARI's operator stays reachable as LibPARI.PARI.gmod.
Restricted to integer-valued arguments, where Base.mod's meaning is the one being matched.
Examples
julia> using LibPARI
julia> LibPARI.pari_mod(7, -3) == mod(7, -3)
trueLibPARI.polroots — Method
polroots(g::Gen) -> Gen
The complex roots of a polynomial Gen, as a t_COL of t_COMPLEX values, computed at the current working precision.
The precision follows setprecision(Gen, bits) like every other precision-taking call.
LibPARI.prevprime — Method
prevprime(n::Gen) -> Gen
The largest prime <= n.
LibPARI.subst — Method
subst(g::Gen, y::Gen) -> Gen
Substitute y for the main variable of g.
LibPARI.to_symbolics — Function
Convert a PARI value to the corresponding expression of another computer algebra system.
This is a generic with no methods of its own: a bridge supplies them. The Symbolics.jl bridge is a package extension, live as soon as Symbolics is loaded alongside LibPARI:
using LibPARI, Symbolics
to_symbolics(gp_eval("x^2 + 1")) # x^2 + 1, as a Symbolics expressionThe inward direction is pari, extended by the same bridge.
A PARI polynomial carries a variable priority — a process-global ordering that decides which variable is the main one, and therefore how the polynomial is structured and printed. Symbolics has no such notion. A round trip preserves the mathematical value and the variable names; it does not promise the same internal ordering, so compare results by value, never by printed form.
PARI containers
Gen is deliberately not an AbstractArray — one concrete type also wraps integers, strings and closures — so the relevant Base methods are defined directly and refuse the PARI types where they mean nothing. A t_MAT reports Julia's (rows, columns), transposing PARI's column-major storage, and element access clones: every element owns its memory and outlives the container it came from.
Base.Matrix — Method
Copy a PARI t_MAT into a Julia Matrix{Gen}, with Julia's (rows, columns) shape.
Throws ArgumentError for anything that is not a matrix — a t_VEC is not silently reshaped.
Base.Vector — Method
Copy a PARI vector or matrix into a Julia Vector{Gen}, in column-major order.
Base.getindex — Method
getindex(g::Gen, i::Integer, j::Integer) -> Any
The element at row i, column j of a PARI t_MAT, as an owned Gen.
Examples
julia> using LibPARI
julia> gp_eval("[1,2,3;4,5,6]")[2, 3]
6Base.getindex — Method
getindex(g::Gen, i::Integer) -> Any
The i-th element of a PARI container, as an owned Gen.
Indices are one-based, as in Julia and as in PARI itself. A t_MAT indexes in column-major order, matching its size.
The element is a clone: it owns its own PARI storage and outlives the container it came from.
Examples
julia> using LibPARI
julia> gp_eval("[10,20,30]")[2]
20Base.length — Method
length(g::Gen) -> Int64
The number of elements in a PARI container.
For a t_MAT this is the element count — rows × columns — as Base.length means it, not PARI's column count (LibPARI.PARI.glength gives that).
Throws ArgumentError for a Gen that is not a container.
Examples
julia> using LibPARI
julia> length(gp_eval("[10,20,30]"))
3Base.size — Method
size(g::Gen) -> Union{Tuple{Int64}, Tuple{Int64, Int64}}
The dimensions of a PARI container, in Julia's order.
A t_MAT gives (rows, columns), transposing PARI's own column-major reading; a vector type gives (n,).
Examples
julia> using LibPARI
julia> size(gp_eval("[1,2,3;4,5,6]"))
(2, 3)Type conversions
LibPARI converts an enumerated set of Julia types, not every Number. The set is LibPARI.PariConvertible and the single entry point is LibPARI.gen_convert; Gen(x), convert(Gen, x) and every mixed-operand operator funnel through it, so one type is converted in exactly one way.
Into a Gen:
| Julia type | PARI type | Notes |
|---|---|---|
Bool | t_INT | 0/1 — PARI has no boolean type, and Bool <: Integer |
Int8 … Int128, UInt8 … UInt128 | t_INT | exact at every width |
BigInt | t_INT | exact, any magnitude |
Rational{<:Integer} | t_FRAC | reduced by PARI; an integral value normalises to t_INT |
Float16, Float32, Float64 | t_REAL | exact |
BigFloat | t_REAL | exact — see Precision |
Complex{T}, T convertible | t_COMPLEX | a zero imaginary part normalises to the real type |
Anything else — an Irrational such as π, a Missing, a foreign numeric type — raises LibPARI.ConversionError, which names the offending type. A downstream package adds support for its own type by defining a LibPARI.gen_convert method for it, which is type piracy on neither side.
Inf, -Inf and NaN raise InexactError: PARI's t_INFINITY exists but does not take part in general arithmetic, so mapping onto it would produce values that fail later, far from the conversion.
Out of a Gen: BigInt, Bool and the fixed-width integer types (InexactError when the value is not an integer or does not fit); Rational and Rational{T}; Float16, Float32, Float64 and BigFloat; Complex and Complex{T}. A t_REAL is decomposed with PARI's own mantissa and exponent rather than re-parsed from its printed form, so the conversion neither loses digits nor fails on a large exponent.
LibPARI.GenArg — Type
What a generated LibPARI.PARI binding accepts where PARI's prototype expects a GEN: a Gen, or any PariConvertible value.
PariConvertible deliberately does not include Gen — it names the Julia types LibPARI converts from. GenArg is the union of both, and is what the generated layer dispatches on so that PARI.nextprime(1000) and PARI.nextprime(pari(1000)) are the same call (REQ-ARG-01).
LibPARI.PariConvertible — Type
The Julia types LibPARI guarantees it can convert to a Gen.
PariConvertible is an enumerated set, deliberately not Number: a rule that accepted every Number would promise conversions LibPARI cannot perform, and the failure would surface far from the call that caused it.
Support a further type by adding a method to gen_convert — that is a method on your own type, so it is not type piracy on either side.
Base.Complex — Method
Complex(g::Gen) -> ComplexF64
Convert a numeric Gen to a Julia Complex{Float64} — the real and imaginary parts of g as Float64s.
Base.Complex — Method
Complex(g::Gen) -> ComplexF64
Convert a numeric Gen to a Complex{T} — its real and imaginary parts each converted to T (REQ-PROM-08).
Base.GMP.BigInt — Method
BigInt(g::Gen) -> BigInt
Convert an integer-valued Gen to an exact Julia BigInt.
Throws InexactError when g is not an integer — a fraction, a real with a fractional part, or a non-numeric value.
Examples
julia> using LibPARI
julia> BigInt(LibPARI.Gen(-123456789))
-123456789Base.MPFR.BigFloat — Method
BigFloat(g::Gen; precision) -> BigFloat
Convert a real-valued Gen to a Julia BigFloat.
With no precision keyword a t_REAL converts exactly: the result carries PARI's own mantissa, at whatever precision that takes — which may exceed the ambient precision(BigFloat). Pass precision to round once to a chosen width instead (REQ-PREC-07).
Throws InexactError when g is not a real number.
Examples
julia> using LibPARI
julia> precision(BigFloat(LibPARI.Gen(1.5); precision = 256))
256Base.Rational — Method
Rational(g::Gen) -> Rational{BigInt}
Convert a rational- or integer-valued Gen to a Julia Rational{BigInt}.
Throws InexactError when g is not a rational number.
Base.Rational — Method
Rational(g::Gen) -> Rational{BigInt}
Convert a rational- or integer-valued Gen to a Rational{T}.
Throws InexactError when g is not rational, or when its numerator or denominator lies outside the range of T (REQ-PROM-08).
Core.Float32 — Method
Float32(g::Gen) -> Float32
Convert a real-valued Gen to a narrower Julia float — Float16 or Float32.
The value is read at full PARI precision and rounded once to F (REQ-PROM-08).
Core.Float64 — Method
Float64(g::Gen) -> Float64
Convert a real-valued Gen to a Julia Float64.
A PARI real too large for Float64 converts to ±Inf, as any other Julia floating-point conversion would.
Throws InexactError when g is not a real number (a complex value, a polynomial, a vector, …).
Core.Type — Method
Convert an integer-valued Gen to a fixed-width Julia integer type T.
T is one of Julia's built-in integer types (Base.BitInteger), BigInt or Bool — the set LibPARI can validate. A third-party Integer subtype still works, through T(BigInt(g)), but warns: LibPARI cannot check that its construction from a BigInt is exact (REQ-PROM-09).
Throws InexactError when g is not an integer, or when its value lies outside the range of T.
Examples
julia> using LibPARI
julia> Int(LibPARI.Gen(255))
255LibPARI.ConversionError — Type
struct ConversionError <: ExceptionRaised when a value cannot be converted to a Gen.
Carries the offending type and the reason, and names gen_convert — the extension point — rather than surfacing as a MethodError inside a Base function the caller never invoked.
LibPARI.Gen — Method
Gen(x::Integer) -> Any
Convert a Julia Integer of any magnitude to an integer-valued Gen (a PARI t_INT).
Examples
julia> using LibPARI
julia> LibPARI.Gen(42) isa LibPARI.Gen
trueLibPARI.gen_convert — Method
gen_convert(g::Gen) -> Gen
Convert x to a Gen — the single conversion entry point.
Every hand-written conversion, every mixed-operand arithmetic method and every convert(Gen, x) funnels through here, so one type is converted in exactly one way. A Gen argument is returned unchanged, never re-cloned.
A value outside PariConvertible, or one whose conversion fails, raises a ConversionError naming the type — never a MethodError from inside a Base function the caller did not invoke.
Examples
julia> using LibPARI
julia> LibPARI.gen_convert(42) == LibPARI.Gen(42)
trueNumeric API
Gen is a PariObject, not a Julia Number — one concrete Gen wraps every PARI object, matrices and strings included. The numeric surface is therefore declared explicitly, not inherited: +, -, *, /, ^, \, ==, <, <= and isless have methods for Gen/Gen and for a Gen against a Julia Integer, AbstractFloat, Rational or Complex, in either operand order. Gen also carries the zero/one identities, the standard predicates (iszero, isinteger, isfinite, …), the elementary operations (abs, sign, inv, conj, real, imag), hash, float, abs2, adjoint, transpose and scalar broadcasting — so a Gen sorts and serves as a Dict/Set key interchangeably with an equal Julia number.
Generic code bounded by T<:Number — parts of LinearAlgebra, other numeric packages — does not accept a Gen; dispatch on PariObject, or convert. An operation that does not apply to a Gen's underlying PARI type raises a catchable PariError.
LibPARI.Gen — Method
Gen(z::Complex) -> Gen
Convert a Julia Complex number to a Gen (a PARI complex value).
Examples
julia> using LibPARI
julia> LibPARI.Gen(3 + 4im) isa LibPARI.Gen
trueLibPARI.Gen — Method
Gen(x::Rational) -> Any
Convert a Julia Rational to a Gen (a reduced PARI rational value).
Examples
julia> using LibPARI
julia> LibPARI.Gen(3 // 4) isa LibPARI.Gen
trueGP expression evaluator
LibPARI.gp_eval — Method
gp_eval(s::AbstractString) -> Any
Evaluate a GP-language expression string with PARI's GP engine and return the result as a Gen.
gp_eval reaches every PARI capability — including the GP-closure-argument functions (sum, intnum, …) that the generated bindings do not expose. A syntactically invalid string raises a catchable PariError describing the parse error; a runtime failure raises a PariError too.
GP state, and the threading rule
There is one GP environment per process, and it lives in PARI's primary context. Variable assignments persist across calls, so gp_eval("x = 42") followed by gp_eval("x + 1") answers 43.
That environment is not reachable for writing from another task. PARI's parallel model makes global variables read-only inside a secondary context, so from a Threads.@spawned task:
- pure evaluation works —
gp_eval("2 + 2")answers4; - reading a variable raises
PariError(e_MISC),"mt: please use export(x)", unless the primary task exported it withgp_eval("export(x)"); - assigning always raises
PariError(e_MISC),"mt: attempt to change exported variable".
This is PARI's design, not a LibPARI restriction: its documentation states that exported variables "cannot be modified inside a parallel section". Confine GP variable work to one task.
Examples
julia> using LibPARI
julia> LibPARI.gp_eval("2 + 2") isa LibPARI.Gen
trueModule
LibPARI.LibPARI — Module
LibPARIA Julia wrapper for the PARI/GP number-theory library.
Loading this module initializes the embedded PARI library once for the process and registers a clean shutdown at process exit. LibPARI exposes PARI/GP in two ways: nearly 1200 functions generated from PARI's own function database, reachable through the LibPARI.PARI submodule, and a hand-written core — the Gen value type, idiomatic numeric operators, conversions to and from Julia numbers, the gp_eval expression evaluator, and safe library lifecycle and error handling.
The lifecycle is observable through LibPARI.is_initialized, LibPARI.library_state, and LibPARI.stack_size.
LibPARI.__init__ — Method
Initialize PARI when the module is loaded into a process (REQ-INI-02, REQ-INI-03). Runs once, never during precompilation; reads the optional LIBPARI_STACK_SIZE configuration and delegates to _init_libpari!.