LGMP - A GMP package for Lua 5.1

Wim Couwenberg - July 2007

The package offers the GNU multiple precision arithmetic library [1] for Lua 5.1. Currently it supports only the integer, floating point and random state types. I have no plans (yet) to add support for rationals.

Building and installing

The package consists of a single C file “lgmp.c” and a single Lua file “gmp.lua”. The libraries for Lua and GMP should already be available on your system. Compile and link lgmp.c into a bundle (OSX), dynamic link library (Win32) or shared library (Unix) called either “c-gmp.so” (OSX, Unix) or “c-gmp.dll” (Win32). Link against both the Lua and GMP libraries if necessary. Here is the command line I use to build c-gmp.so on OSX 10.4.10 (the Lua library is a dylib and the GMP library is a static archive on my system):

gcc -bundle -O2 -Wall -llua -lgmp -o c-gmp.so lgmp.c

Place the file c-gmp.so (or c-gmp.dll) and gmp.lua in the proper locations on your system so that they will be found through package.cpath and package.path respectively.

Using LGMP

Load the lgmp package with require “gmp”. This makes the lgmp functionality available through a global table named “gmp”. The package defines a handful of global functions to create and compute gmp objects. Objects can be manipulated through a large number of methods. The lgmp package covers most of the GMP library functions available for integer, floating point and random state types. The string gmp.version reflects the version of the underlying GMP library. On my system it currently reads:

> =gmp.version
4.2.1

Mutable types

All lgmp types are mutable, i.e. the value of an instance can change. This is hardly surprising for a random state but it can become a bit confusing for integer and floating point types. The library is set up in such a way that most functions and methods do not change their operands by default. (Though some methods, like set, addmul and submul, are designed to update their self operand.) The design of the lgmp package with respect to mutability is as follows. Whenever a function or method returns n objects of integer or floating point type, then that function or method accepts n optional extra arguments that can specify existing objects of the same type. When these extra arguments are provided then their value is changed and the function or method returns these arguments. The following examples illustrate this principle.


> -- load lgmp package
> require “gmp”

> -- create two gmp integers
> x = gmp.z(123)
> y = gmp.z(456)

> -- compute their sum
> =x:add(y)
579

> -- x and y are left unchanged
> =x, y
123	456

> -- compute sum, update and return x
> =x:add(y,x)
579

> -- x is updated
> =x, y
579	456

> -- compute quotient and remainder
> =x:fdiv_qr(y)
1	123

> -- x and y are left unchanged
> =x, y
579	456

> -- update y with remainder and return quotient, y
> =x:fdiv_qr(y, nil, y)
1	123

> -- y is updated, x is left unchanged
> =x, y
579	123

> -- update x and y to quotient and remainder and return x, y
> =x:fdiv_qr(y, x, y)
4	87

> -- x and y are both updated
> =x, y
4	87

> -- returns nothing but updates “self”
> =x:addmul(y, 3)
> =x, y
265	87

> -- returns nothing but sets “self” to new integer value
> =x:set "123456789123456789123456789"
> =x
123456789123456789123456789

Global functions

The table below lists the global functions in the lgmp package. Arguments in italics are optional. Refer to the GMP manual [2] for further details.

Function Implemented with Description
bin(a1, a2, res) mpz_bin_ui
mpz_bin_uiui
Computes the binomial coefficient a1 over a2. Argument a1 may be negative. Argument a2 must be a Lua number in the unsigned long range. Returns a gmp integer.
f(value, base) mpf_init
mpf_init_set
mpf_init_set_d
mpf_init_set_str
mpf_init_set_z
Create a floating point object. If no initial value is specified then it is initialized to 0 (zero). The inital value can be a Lua number, an integer object, a floating point object or a string. If value is a string then base can optionally specify the base between -62 and -2 or between 2 and 62 inclusive. (Refer to the mpf_set_str function in the GMP manual [2] for details.) If no base is specified it defaults to 10.
fac(a, res) mpz_fac_ui Argument a must be a Lua number in the unsigned long range.
fib(a, res)
fib2(a, r1, r2)
mpz_fib_ui
mpz_fib2_ui
Argument a must be a Lua number in the unsigned long range.
lucnum(a, res)
lucnum2(a, r1, r2)
mpz_lucnum_ui
mpz_lucnum2_ui
Argument a must be a Lua number in the unsigned long range.
pow(a1, a2, res) mpz_pow_ui
mpz_ui_pow_ui
Argument a2 must be a Lua number in the unsigned long range. Returns a gmp integer.
rand(a) gmp_randinit_default
gmp_randinit_set
Create a random state object. An initial random state can be provided in a to create a copy of that state. If no argument is provided then a default random state is created.
set_default_prec(a) mpf_set_default_prec Set default minimal precision for new floating point objects to a bits.
sqrt(a, res) mpf_sqrt_ui The argument a must be in the unsigned long range. Returns a floating point number.
z(value, base) mpz_init
mpz_init_set
mpz_init_set_d
mpz_init_set_f
mpz_init_set_str
Create an integer object. If no arguments are given then its value is initialized to 0 (zero). The initial value can be specified as a Lua number, an integer object, a floating point object or a string. If value is a string then base can be optionally specify a base between 2 and 62 (inclusive) or base can be 0 (zero) in which case the actual base is implied by a prefix of value. (Refer to the mpz_set_str function in the GMP manual [2] for details.) If no base is specified it defaults to 10.

Integer methods

The table below lists the methods of an integer object. Arguments in italics are optional. Refer to the GMP manual [2] for further details.

Method Implemented with Description
z:__tostring() mpz_get_str
z:__concat(a) mpz_get_str
z:__add(a)
z:__sub(a)
mpz_add
mpz_add_ui
mpz_sub
mpz_sub_ui
mpz_ui_sub
z:__mul(a) mpz_mul
mpz_mul_si
mpz_mul_ui
z:__div(a)
z:__mod(a)
mpz_fdiv_q
mpz_fdiv_q_ui
mpz_fdiv_r
mpz_fdiv_r_ui
The implementations of __div and __mod are chosen such that __mod extends the Lua % operator and x = (x/y)*y + x%y for all integer objects x and y.
z:__pow(a) mpz_pow_ui The exponent a must be in the unsigned long range.
z:__unm() mpz_neg
z:__lt(a)
z:__le(a)
z:__eq(a)
mpz_cmp
z:__gc() mpz_clear
z:abs(res) mpz_abs
z:add(a, res) mpz_add
mpz_add_ui
z:addmul(a1, a2) mpz_addmul
mpz_addmul_ui
Changes self to self + a1*a2. Returns nothing.
z:And(a, res) mpz_and Named with a capital A to avoid a name clash with the built-in operator and.
z:bin(a, res) mpz_bin_ui Computes the binomial coefficient self over a. The value of self may be negative. Argument a must be a Lua number in the unsigned long range.
z:cdiv_q(a, res)
z:cdiv_q_2exp(a, res)
z:cdiv_qr(a, r1, r2)
z:cdiv_r(a, res)
z:cdiv_r_2exp(a, res)
z:cdiv(a)
mpz_cdiv_q
mpz_cdiv_q_ui
mpz_cdiv_q_2exp
mpz_cdiv_r
mpz_cdiv_r_ui
mpz_cdiv_r_2exp
mpz_cdiv_qr
mpz_cdiv_qr_ui
mpz_cdiv_ui
If a is a Lua number in the (un)signed long range then z:cdiv_q, z:cdiv_r and z:cdiv_qr all return the remainder as an additional Lua number return value. The method z:cdiv takes an argument in the (un)signed long range and returns only the remainder as a Lua number.
z:clrbit(a, res) mpz_clrbit
z:cmp(a)
z:cmpabs(a)
mpz_cmp
mpz_cmp_d
mpz_cmp_si
mpz_cmp_ui
z:com(res)
z:combit(a, res)
mpz_com
mpz_combit
z:congruent(a1, a2)
z:congruent_2exp(a1, a2)
mpz_congruent_p
mpz_congruent_ui_p
mpz_congruent_2exp_p
Result is a boolean
z:divexact(a, res) mpz_divexact
mpz_divexact_ui
Result is a boolean
z:divisible(a)
z:divisible_2exp(a)
mpz_divisible_p
mpz_divisible_ui_p
mpz_divisible_2exp_p
Result is a boolean
z:fdiv_q(a, res)
z:fdiv_q_2exp(a, res)
z:fdiv_qr(a, r1, r2)
z:fdiv_r(a, res)
z:fdiv_r_2exp(a, res)
z:fdiv(a)
mpz_fdiv_q
mpz_fdiv_q_ui
mpz_fdiv_q_2exp
mpz_fdiv_r
mpz_fdiv_r_ui
mpz_fdiv_r_2exp
mpz_fdiv_qr
mpz_fdiv_qr_ui
mpz_fdiv_ui
If a is a Lua number in the (un)signed long range then z:fdiv_q, z:fdiv_r and z:fdiv_qr all return the remainder as an additional Lua number return value. The method z:fdiv takes an argument in the (un)signed long range and returns only the remainder as a Lua number.
z:fits_sint()
z:fits_slong()
z:fits_sshort()
z:fits_uint()
z:fits_ulong()
z:fits_ushort()
mpz_fits_sint_p
mpz_fits_slong_p
mpz_fits_sshort_p
mpz_fits_uint_p
mpz_fits_ulong_p
Result is a boolean
z:format(fmt, prec) gmp_asprintf Formats self according to the format specifier fmt. The leading ‘%’ character is optional. The type ‘Z’ is implied but may be specified explicitly. The conversion character is restricted to one of “dioxX”. If the precision is given by “.*” then the second argument prec must specify the precision. Otherwise prec must be unspecified.
z:gcd(a, res)
z:gcdext(a, r1, r2, r3)
mpz_gcd
mpz_gcd_ui
mpz_gcdext
z:get_d()
z:get_d_2exp()
mpz_get_d
mpz_get_d_2exp
z:get_str(base) mpz_get_str If base is not specified it defaults to 10.
z:hamdist(a) mpz_hamdist
z:invert(a, res) mpz_invert Returns nothing if no inverse exists
z:ior(a, res) mpz_ior
z:jacobi(a)
z:legendre(a)
z:kronecker(a)
mpz_kronecker
mpz_kronecker_si
mpz_kronecker_ui
The functions z:jacobi, z:legendre and z:kronecker are identical
z:rjacobi(a)
z:rlegendre(a)
z:rkronecker(a)
mpz_kronecker
mpz_si_kronecker
mpz_ui_kronecker
As z:jacobi, z:legendre and z:kronecker but with reversed arguments. All three functions are identical
z:lcm(a, res) mpz_lcm
mpz_lcm_ui
z:mod(a, res) mpz_mod
mpz_fdiv_r_ui
If a is a Lua number in the (un)signed long range then the modulus as a Lua number is returned as a second return value.
z:mul(a, res)
z:mul_2exp(a, res)
mpz_mul
mpz_mul_si
mpz_mul_ui
mpz_mul_2exp
z:neg(res) mpz_neg
z:nextprime(res) mpz_nextprime
z:perfect_power() mpz_perfect_power_p Result is a boolean
z:perfect_square() mpz_perfect_square_p Result is a boolean
z:popcount() mpz_popcount
z:pow(a, res) mpz_pow_ui The exponent a must be in the unsigned long range.
z:powm(a1, a2, res) mpz_powm
mpz_powm_ui
z:probab_prime(a) mpz_probab_prime_p Result is false, 1 or 2. If the number a of tests is not specified it defaults to 10.
z:remove(a, res) mpz_remove
z:root(a, res)
z:rootrem(a, r1, r2)
mpz_root
mpz_rootrem
z:scan0(a)
z:scan1(a)
mpz_scan0
mpz_scan1
A a is not specified then it defaults to 0 (zero).
z:set(a, base) mpz_set
mpz_set_d
mpz_set_f
mpz_set_str
Changes the value of self. Returns nothing. If a is a string then an optional base can be specified. See the description of global function z for further details.
z:setbit(a, res) mpz_setbit
z:sgn() mpz_sgn
z:sizeinbase(a) mpz_sizeinbase If the base a is not specified then it defaults to 10.
z:sqrt(res)
z:sqrtrem(r1, r2)
mpz_sqrt
mpz_sqrtrem
z:sub(a, res)
z:rsub(a, res)
mpz_sub
mpz_sub_ui
mpz_ui_sub
Method z:rsub acts as z:sub but with reversed operands.
z:submul(a1, a2) mpz_submul
mpz_submul_ui
Changes the value of self to self - a1*a2. Returns nothing.
z:tdiv_q(a, res)
z:tdiv_q_2exp(a, res)
z:tdiv_qr(a, r1, r2)
z:tdiv_r(a, res)
z:tdiv_r_2exp(a, res)
z:tdiv(a)
mpz_tdiv_q
mpz_tdiv_q_ui
mpz_tdiv_q_2exp
mpz_tdiv_r
mpz_tdiv_r_ui
mpz_tdiv_r_2exp
mpz_tdiv_qr
mpz_tdiv_qr_ui
mpz_tdiv_ui
If a is a Lua number in the (un)signed long range then z:tdiv_q, z:tdiv_r and z:tdiv_qr all return the remainder as an additional Lua number return value. The method z:tdiv takes an argument in the (un)signed long range and returns only the remainder as a Lua number.
z:tstbit(a) mpz_tstbit Returns 0 or 1.
z:xor(a, res) mpz_xor

Floating point methods

The table below lists the methods of floating point object. Arguments in italics are optional. Refer to the GMP manual [2] for further details.

Method Implemented with Description
f:__tostring()
f:__concat(a)
gmp_asprintf The floating point is formatted with the format specifier “%.Fg”.
f:__add(a)
f:__sub(a)
mpf_add
mpf_add_ui
mpf_sub
mpf_sub_ui
mpf_ui_sub
f:__mul(a) mpf_mul
mpf_mul_ui
f:__div(a) mpf_div
mpf_div_ui
mpf_ui_div
f:__unm() mpf_neg
f:__pow(a) mpf_pow_ui The exponent a must be in the unsigned long range.
f:__lt(a)
f:__le(a)
f:__eq(a)
mpf_cmp
mpf_cmp_d
mpf_cmp_si
mpf_cmp_ui
f:__gc() mpf_clear
f:abs(res) mpf_abs
f:add(a, res) mpf_add
mpf_add_ui
f:ceil(res) mpf_ceil
f:cmp(a) mpf_cmp
mpf_cmp_d
mpf_cmp_si
mpf_cmp_ui
f:div(a, res)
f:rdiv(a, res)
mpf_div
mpf_div_ui
mpf_ui_div
The function f:rdiv is identical to f:div but with reversed arguments.
f:eq(a1, a2) mpf_eq Result is a boolean.
f:fits_sint()
f:fits_sshort()
f:fits_uint()
f:fits_ulong()
f:fits_ushort()
mpf_fits_sint_p
mpf_fits_sshort_p
mpf_fits_uint_p
mpf_fits_ulong_p
mpf_fits_ushort_p
Result is a boolean.
f:floor(res) mpf_floor
f:format(fmt, prec) gmp_asprintf Formats self according to the format specifier string fmt. The leading ‘%’ character is optional. The type ‘F’ is implied but may be specified explicitly. The conversion character is restricted to one of “aAeEfgG”. If the precision is given by “.*” then prec must specify the precision. Otherwise prec must be unspecified.
f:get_d()
f:get_d_2exp()
mpf_get_d
mpf_get_d_2exp
f:get_prec() mpf_get_prec
f:get_str(base, size) mpf_get_str Returns a string of digits and an exponent. If base is unspecified it defaults to 10. If size is unspecified it defaults to the precision of self in the given base.
f:integer() mpf_integer_p Result is a boolean.
f:mul(a, res)
f:mul_2exp(a, res)
mpf_mul
mpf_mul_ui
mpf_mul_2exp
f:neg(res) mpf_neg
f:pow(a, res) mpf_pow_ui The exponent a must be int the unsigned long range.
f:reldiff(a, res) mpf_reldiff
f:set_prec(a) mpf_set_prec
f:set(a, base) mpf_set
mpf_set_d
mpf_set_str
mpf_set_z
Change the value of self. Returns nothing. See the description of the global function f for details.
f:sgn() mpf_sgn
f:sqrt(res) mpf_sqrt
f:sub(a, res)
f:rsub(a, res)
mpf_sub
mpf_sub_ui
mpf_ui_sub
Method f:rsub is identical to f:sub but with reversed arguments.
f:trunc(res) mpf_trunc

Random state methods

The table below lists the methods of a random state object. Arguments in italics are optional. Refer to the GMP manual [2] for further details.

Method Implemented with Description
rand:__tostring() N/A
rand:__gc() gmp_randclear
rand:seed(a) gmp_randseed
gmp_randseed_ui
Set a seed value for the random state.
rand:zbits(a, res) mpz_urandomb Generate an integer of at most a bits.
rand:z(a, res) mpz_urandomm Generate an integer in the interval [0, a).
rand:fbits(a, res) mpf_urandomb Generate a floating point in the interval [0, 1) with a mantissa of at most a bits.

License

The lgmp package is distributed under the MIT license. See the “COPYRIGHT” file in the distribution of lgmp.

References

[1] GMP «Arithmetic without limitations»
[2] GNU MP Manual