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 Help text as its docstring — query it with ? at the REPL, e.g. ?LibPARI.PARI.nextprime;
  • takes and returns Gen values (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 prec keyword 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_eval instead.

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

Library lifecycle

LibPARI.LibraryStateModule

Lifecycle states of the embedded PARI library.

LibraryState.T is a module-scoped enum with three values:

  • UNINITIALIZEDpari_init has not (successfully) run
  • INITIALIZED — PARI is ready; a process-exit shutdown is registered
  • CLOSEDpari_close has run at process exit
source
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).

source
LibPARI._configured_stack_sizeMethod

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.

source
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).

source
LibPARI._validate_parisizeMethod

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.

source
LibPARI.is_initializedMethod
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()
true
source
LibPARI.library_stateMethod
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
true
source
LibPARI.stack_sizeMethod
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
true
source

The Gen value type

LibPARI.GenType
mutable struct Gen <: LibPARI.PariObject

A 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)
true
source
LibPARI.PariObjectType
abstract type PariObject

The 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
true
source
LibPARI.gen_fromMethod

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
true
source
LibPARI.gentypeMethod
gentype(g::Gen) -> LibPARI.PariType.T

Return the PARI value type of g as a PariType.TT_INT, T_REAL, T_POL, T_VEC, and so on.

Examples

julia> using LibPARI

julia> LibPARI.gentype isa Function
true
source
LibPARI.PariTypeModule

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.

source

Error handling

LibPARI.PariErrModule

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.

source
LibPARI.PariErrorType
struct PariError <: Exception

Exception 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
true
source
LibPARI.protected_callMethod

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
true
source

The 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.denominatorMethod
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.

source
Base.factorialMethod
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))
2432902008176640000
source
Base.gcdMethod
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)
6
source
Base.gcdxMethod
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)
true
source
Base.invmodMethod
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.

source
Base.numeratorMethod
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.

source
Base.powermodMethod
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.

source
LibPARI.ModMethod
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)
source
LibPARI.coeffMethod
coeff(g::Gen, k::Integer) -> Any

The coefficient of x^k in a polynomial Gen, as a Gen.

source
LibPARI.degreeMethod
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.

source
LibPARI.factorMethod
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.

source
LibPARI.factorsMethod
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)
source
LibPARI.isprimeMethod
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)
true
source
LibPARI.liftMethod
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))
5
source
LibPARI.nextprimeMethod
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.

source
LibPARI.pariMethod
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
true
source
LibPARI.pari_modMethod
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)
true
source
LibPARI.polrootsMethod
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.

source
LibPARI.substMethod
subst(g::Gen, y::Gen) -> Gen

Substitute y for the main variable of g.

source
LibPARI.to_symbolicsFunction

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 expression

The inward direction is pari, extended by the same bridge.

Value-preserving, not representation-preserving

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.

source

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.MatrixMethod

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.

source
Base.VectorMethod

Copy a PARI vector or matrix into a Julia Vector{Gen}, in column-major order.

source
Base.getindexMethod
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]
6
source
Base.getindexMethod
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]
20
source
Base.lengthMethod
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]"))
3
source
Base.sizeMethod
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)
source

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 typePARI typeNotes
Boolt_INT0/1 — PARI has no boolean type, and Bool <: Integer
Int8Int128, UInt8UInt128t_INTexact at every width
BigIntt_INTexact, any magnitude
Rational{<:Integer}t_FRACreduced by PARI; an integral value normalises to t_INT
Float16, Float32, Float64t_REALexact
BigFloatt_REALexact — see Precision
Complex{T}, T convertiblet_COMPLEXa 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.GenArgType

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).

source
LibPARI.PariConvertibleType

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.

source
Base.ComplexMethod
Complex(g::Gen) -> ComplexF64

Convert a numeric Gen to a Julia Complex{Float64} — the real and imaginary parts of g as Float64s.

source
Base.ComplexMethod
Complex(g::Gen) -> ComplexF64

Convert a numeric Gen to a Complex{T} — its real and imaginary parts each converted to T (REQ-PROM-08).

source
Base.GMP.BigIntMethod
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))
-123456789
source
Base.MPFR.BigFloatMethod
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))
256
source
Base.RationalMethod
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.

source
Base.RationalMethod
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).

source
Core.Float32Method
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).

source
Core.Float64Method
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, …).

source
Core.TypeMethod

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))
255
source
LibPARI.ConversionErrorType
struct ConversionError <: Exception

Raised 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.

source
LibPARI.GenMethod
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
true
source
LibPARI.gen_convertMethod
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)
true
source

Numeric 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.GenMethod
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
true
source
LibPARI.GenMethod
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
true
source

GP expression evaluator

LibPARI.gp_evalMethod
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") answers 4;
  • reading a variable raises PariError(e_MISC), "mt: please use export(x)", unless the primary task exported it with gp_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
true
source

Module

LibPARI.LibPARIModule
LibPARI

A 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.

source
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!.

source