Lua logo

Preface

This is the reference manual of MoonGLMATH, which is a Lua math library for MoonGL. [1]

It is assumed that the reader is familiar with the Lua programming language.

For convenience of reference, this document contains external (deep) links to the Lua Reference Manual.

Getting and installing

For installation intructions, refer to the README file in the MoonGLMATH official repository on GitHub.

Module organization

The MoonGLMATH module is loaded using Lua’s require() and returns a table containing the functions it provides (as usual with Lua modules). This manual assumes that such table is named glmath, i.e. that it is loaded with:

 glmath = require("moonglmath")

but nothing forbids the use of a different name.

Examples

A few examples can be found in the examples/ directory of the release package.

License

MoonGLMATH is released under the MIT/X11 license (same as Lua, and with the same only requirement to give proper credits to the original author). The copyright notice is in the LICENSE file in the base directory of the official repository on GitHub.

See also

MoonGLMATH is part of MoonLibs, a collection of Lua libraries for graphics and audio programming.

Introduction

MoonGLMATH is a basic graphics math library in Lua, intended to be used with MoonGL and the other libraries of the MoonLibs collection (but it does not depend on them, and viceversa).

By now it has only the minimal features needed for graphics programming: real vectors and real matrices up to 4 and 4x4 dimensions, quaternions, 2D and 3D axis-aligned boxes, 2D axis-aligned rectangles, complex numbers, and a few functions to generate transformation matrices.

Like MoonGL and the other companion libraries, it is not designed for performance but for ease of use (the main purpose of these libraries is to lighten the burden of programming while studying computer graphics).

Vectors

MoonGLMATH supports row and column numeric vectors of size 2, 3, and 4.

A vector v is implemented as a table having the vector elements in the array part, starting from index 1. Additionally, it also has the non-array fields v.size (= 2, 3, or 4) and v.type (= 'column' or 'row').

Vector elements are Lua numbers and can be accessed through standard indexing (that is, v[1] is the first element, v[2] is the second element and so on).

Vector elements can also be accessed using the xyzw, rgba and stpq syntactic sugar for positions, colors and texture coordinates (v.x, v.r and v.s are aliases for v[1], v.y, v.g and v.t are aliases for v[2], and so on).

The following constructors can be used to create vectors.

  • v = vec2(…​)
    v = vec3(…​)
    v = vec4(…​)
    v = vec2r(…​)
    v = vec3r(…​)
    v = vec4r(…​)
    Create a vector. The vecN function creates a column vector of size N (where N may be 2, 3 or 4), whereas the vecNr function creates a row vector of the same size. Values to initialize the vector elements may be optionally passed as a list of numbers, or as a previously created vector (exceeding values are discarded, while missing values are replaced with zeros).

  • t = tovec2(t)
    t = tovec3(t)
    t = tovec4(t)
    t = tovec2r(t)
    t = tovec3r(t)
    t = tovec4r(t)
    Turn an appropriately sized table into a vector, by adding the relevant meta information to it.

examples
v = glmath.vec3()            --> v = { 0, 0, 0 }'
v = glmath.vec3(11, 22)      --> v = { 11, 22, 0 }'
v = glmath.vec2(v)           --> v = { 11, 22 }'
v = glmath.vec4(v)           --> v = { 11, 22, 0, 0 }'
v = glmath.vec2(1, 2, 3, 4)  --> v = { 1, 2 }'
  • boolean = isvec2(v)
    boolean = isvec3(v)
    boolean = isvec4(v)
    boolean = isvec2r(v)
    boolean = isvec3r(v)
    boolean = isvec4r(v)
    Check if v is a vector of a given type (e.g. isvec2r checks if v is a row vector of size 2).


Vectors have the following functions, also available as methods of their first argument:

  • |v| = norm(v)
    |v|2 = norm2(v)
    v/|v| = normalize(v)
    vT = transpose(v)

  • vclamped = clamp(v, vmin, vmax)
    Element-wise clamp.

  • vmix = mix(v, v1, k)
    Element-wise blend vmix = (1-k)*v +k*v1, where k is a number.

  • vstep = step(v, vedge)
    Element-wise step: vstep=0.0 if v≤vedge, vstep=1.0 otherwise (element subscripts are omitted for clarity).
    The vedge argument may be a number, meaning a vector with all elements equal to that number.

  • vsmoothstep = smoothstep(v, v0, v1)
    Element-wise smoothstep: omitting element subscripts, vsmoothstep is 0.0 if v≤v0, 1.0 if v≥v1, and is obtained by smooth Hermite interpolation if v0<v<v1 (i.e. vsmoothstep=3t2-2t3, where t=(v-v0)/(v1-v0)). The result is undefined if v0≥v1.
    The v0 and v1 argument may be both be a number, meaning a vector with all elements equal to that number.

  • vfade = fade(v, v0, v1)
    Element-wise improved smoothstep. Same as smoothstep( ), but with the smoother interpolation function vfade=6t5-15t4+10t3 (Perlin improved).


The following vector operators are supported:

  • Unary minus: v = -v1.

  • Addition: v = v1 + v2.

  • Subtraction: v = v1 - v2.

  • Multiplication by a scalar: v = s * v1, and v = v1 * s, where s is a number.

  • Division by a scalar: v = v1 / s, where s is a number.

  • Dot product: s = v1 * v2, where v1 and v2 are vectors of the same size (row*column, but row*row and column*column are accepted as well).

  • Multiplication: m = v1 * v2, where v1 is a column vector and v2 is a row vector of the same size. The result is a square matrix.

  • Cross product: v = v1 % v2, where v1 and v3 are size 3 vectors. Works also on operands of size 2 and 4, adapting them to size 3 (size 2 operands are extended to size 3 by adding a zero element, while size 4 operands are reduced to size 3 by ignoring the 4-th element). The result is always a size 3 vector.

Matrices

MoonGLMATH supports numeric matrices of size NxM, with N and M ranging from 2 to 4 inclusive.

A matrix m is implemented as a table having its rows in the array part, starting from index 1; each row is also a table having the elements in the array part. Additionally, the matrix also has the non-array fields m.rows and m.columns, whose values are the number of rows and of columns, respectively.

Matrix elements are Lua numbers and can be accessed through standard indexing. That is, m[i][j] is the element in the i-th row and j-th column of the matrix m.

Matrix elements can also be accessed using the m._ij syntactic sugar, with i and j ranging from 1 to 4 inclusive, which is an alias for m[i][j] (e.g. m._23 is the same as m[2][3]).

The following constructors can be used to create matrices.

  • m = mat2(…​)
    m = mat3(…​)
    m = mat4(…​)
    m = mat2x3(…​)
    m = mat3x2(…​)
    m = mat2x4(…​)
    m = mat4x2(…​)
    m = mat3x4(…​)
    m = mat4x3(…​)
    Create a matrix. The matN function creates a square matrix vector size NxN, while the matNxM creates a rectangular matrix of size NxM. Values to initialize the matrix elements may be optionally passed as a list of numbers (to fill the matrix in row-major order), as a list of row vectors (to fill the matrix rows), as a list of column vectors (to fill the matrix columns), or as a matrix (to copy the elements from). In all cases, exceeding values are discarded, while missing values are replaced with zeros. As an exception, the matN function, when invoked without arguments, returns the NxN identity matrix.

  • t = tomat2(t)
    t = tomat3(t)
    t = tomat4(t)
    t = tomat2x3(t)
    t = tomat3x2(t)
    t = tomat2x4(t)
    t = tomat4x2(t)
    t = tomat3x4(t)
    t = tomat4x3(t)
    Turn an appropriately sized table into a matrix, by adding the relevant meta information to it.

examples
m = glmath.mat3()              --> m = {{ 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }}
m = glmath.mat2x3()            --> m = {{ 0, 0, 0 }, { 0, 0, 0 }}
m = glmath.mat2x3(1, 2, 3, 4)  --> m = {{ 1, 2, 3 }, { 4, 0, 0 }}
m = glmath.mat3x2(1, 2, 3, 4)  --> m = {{ 1, 2 }, { 3, 4 }, { 0, 0 }}
m = glmath.mat3(m)             --> m = {{ 1, 2, 0 }, { 3, 4, 0 }, { 0, 0, 0 }}
v1 = glmath.vec2(1, 2)
v2 = glmath.vec2(3, 4)
m = glmath.mat2(v1, v2)        --> m = {{ 1, 3 }, { 2, 4 }}
m = glmath.mat3(v1, v2)        --> m = {{ 1, 3, 0 }, { 2, 4, 0 }, { 0, 0, 0 }}
v1 = glmath.vec2r(1, 2)
v2 = glmath.vec2r(3, 4)
m = glmath.mat2(v1, v2)        --> m = {{ 1, 2 }, { 3, 4 }}
m = glmath.mat3(v1, v2)        --> m = {{ 1, 2, 0 }, { 3, 4, 0 }, { 0, 0, 0 }}
  • boolean = ismat2(v)
    boolean = ismat3(v)
    boolean = ismat4(v)
    boolean = ismat2x3(v)
    boolean = ismat3x2(v)
    boolean = ismat2x4(v)
    boolean = ismat4x2(v)
    boolean = ismat3x4(v)
    boolean = ismat4x3(v)
    Check if m is a matrix of a given size (e.g. ismat2 checks if m is a 2x2 matrix).


Matrices have the following functions and methods (functions are also available as methods of their first argument):

  • determinant = det(m)
    trace = trace(m)
    adjoint = adj(m)
    m-1 = inv(m)
    Apply only to square matrices. If m is singular, inv(m) returns nil.

  • mT = transpose(m)

  • q = quat(m)

  • v = m:row(i)
    Returns the i-th row as a row vector (vecNr).

  • v = m:column(i)
    Returns the i-th column as a column vector (vecN).

  • mclamped = clamp(m, mmin, mmax)
    Element-wise clamp.

  • mmix = mix(m, m1, k)
    Element-wise blend mmix = (1-k)*m +k*m1, where k is a number.

  • mstep = step(m, medge)
    Element-wise step: mstep=0.0 if m≤medge, mstep=1.0 otherwise (element subscripts are omitted for clarity).
    The medge argument may be a number, meaning a matrix with all elements equal to that number.

  • msmoothstep = smoothstep(m, m0, m1)
    Element-wise smoothstep: omitting element subscripts, msmoothstep is 0.0 if m≤m0, 1.0 if m≥m1, and is obtained by smooth Hermite interpolation if m0<m<m1 (i.e. msmoothstep=3t2-2t3, where t=(m-m0)/(m1-m0)). The result is undefined if m0≥m1.
    The m0 and m1 argument may be both be a number, meaning a matrix with all elements equal to that number.

  • mfade = fade(m, m0, m1)
    Element-wise improved smoothstep. Same as smoothstep( ), but with the smoother interpolation function mfade=6t5-15t4+10t3 (Perlin improved).


The following matrix operators are supported:

  • Unary minus: m = -m1.

  • Addition: m = m1 + m2.

  • Subtraction: m = m1 - m2.

  • Multiplication by a scalar: m = s * m1, and m = m1 * s, where s is a number.

  • Division by a scalar: m = m1 / s, where s is a number.

  • Integer power: m = m1 ^ n, where m1 is a square matrix and n is an integer.

  • Matrix multiplication: m = m1 * m2, where m1 is a NxK matrix and m2 a KxM matrix. The result m is an NxM matrix.

  • Matrix-vector multiplication: u = m * v where m is an NxM matrix and v is a size M column vector. The result u is a size N column vector.

  • Vector-matrix multiplication: u = v * m where v is a size N row vector and m is an NxM matrix. The result u is a size M row vector.

Quaternions

A quaternion q = (w, v) = w + i·x + j·y + k·z is implemented as a table having the quaternion elements in the array part, starting from index 1.

Quaternion elements are Lua numbers and can be accessed through standard indexing (that is, q[1] is the scalar part w, and q[2] to q[4] are the x, y and z components of the vector part, or imaginary part, v).

Quaternion elements can also be accessed using the wxyz syntactic sugar: q.w, q.x, q.y, and q.z are aliases for q[1], q[2], q[3], and q[4], respectively.

The following constructor can be used to create quaternions.

  • q = quat([w], [x], [y], [z])
    q = quat(w, v)
    q = quat(vaxis, angle)
    q = quat(q)
    q = quat(m)
    Create a quaternion. Values to initialize the quaternion elements may be optionally passed as a list of numbers, as a scalar w and a vector v, or as a previously created quaternion q (exceeding values are discarded, while missing values are replaced with zeros). If a matrix m is passed instead, the constructor assumes - without checking it - that m is a rotation matrix and returns the equivalent quaternion (m may be either a 3x3 or a 4x4 matrix, in which case its upper-left 3x3 submatrix is regarded as the rotation matrix).

  • t = toquat(t)
    Turn an appropriately sized table into a quaternion, by adding the relevant meta information to it.

examples
q = glmath.quat()            --> q = < 0, 0, 0 >
q = glmath.quat(0, 1, 2, 3)  --> q = < 0, 1, 2, 3 >

w = 0
v = glmath.vec3(1, 2, 3)
q = glmath.quat(w, v)        --> q = < 0, 1, 2, 3 >

m = glmath.mat3(1, 0, 0, 0, 0, -1, 0, 1, 0)
q = glmath.quat(m)           --> q = < 0.707107,  0.707107, 0, 0 >
  • boolean = isquat(q)
    Returns true if q is a quaternion, false otherwise.


Quaternions have the following functions and methods (functions are also available as methods of their first argument):

  • w, v = parts(q)
    Returns the scalar and vector parts of q (w is a number and v is a vec3).

  • q* = conj(q)
    |q| = norm(q)
    |q|2 = norm2(q)
    q/|q| = normalize(q)
    q-1 = inv(q)

  • m = q:mat3( )
    m = q:mat4( )
    Convert the quaternion q to a 3x3 or a 4x4 rotation matrix.

  • qmix = mix(q, q1, k)
    Element-wise blend qmix = (1-k)*q +k*q1, where k is a number.

  • qslerp = slerp(q, q1, k)
    Spherical linear interpolation.


The following quaternion operators are supported:

  • Unary minus: q = -q1.

  • Addition: q = q1 + q2.

  • Subtraction: q = q1 - q2.

  • Multiplication by a scalar: q = s * q1, and q = q1 * s, where s is a number.

  • Division by a scalar: q = q1 / s, where s is a number.

  • Integer power: q = q1 ^ n, where n is an integer.

  • Quaternion multiplication: q = q1 * q2.

Boxes

MoonGLMATH supports 2D and 3D axis-aligned boxes.

A box b is implemented as a table having the field b.dimensions (= 2 or 3), and the coordinates of the vertices in the array part, starting from index 1, as follows:

  • { minx, maxx, miny, maxy } if v.dimensions=2 (2D box), or

  • { minx, maxx, miny, maxy, minz, maxz } if v.dimensions=3 (3D box).

The coordinates are Lua numbers and can be accessed through standard indexing (that is, b[1] is minx, b[2] is maxx, and so on). They can also be accessed using the following syntactic sugar: b.minx is an alias for b[1], b.maxx is an alias for b[2], and so on.

The following constructors can be used to create boxes.

  • b = box2(…​)
    b = box3(…​)
    Create an axis-aligned box. The boxN function creates a N-dimensional box (where N may be 2 or 3). Values to initialize the box coordinates may be optionally passed as a list of numbers, or as a previously created box (exceeding values are discarded, while missing values are replaced with zeros). No consistency check is performed on the passed coordinates.

  • t = tobox2(t)
    t = tobox3(t)
    Turn an appropriately sized table into a box, by adding the relevant meta information to it.

examples
b = glmath.box2()               --> b = [ 0, 0, 0, 0 ]
b = glmath.box3()               --> b = [ 0, 0, 0, 0, 0, 0 ]
b = glmath.box3(-1, 1, -2, 2)   --> b = [ -1, 1, -2, 2 ]
  • boolean = isbox2(b)
    boolean = isbox3(b)
    Check if b is a box of the given dimensions (e.g. isbox2 checks if b is a 2D box).

Rectangles

MoonGLMATH supports 2D axis-aligned rectangles, which are essentially the same as 2D boxes but specified differently.

A rect r is implemented as a table having, in the array part, the coordinates (x, y) of its lower-left corner and its width w and height h, as follows: { x, y, w, h }.

The coordinates are Lua numbers and can be accessed through standard indexing (that is, r[1] is x, r[2] is y, and so on). They can also be accessed using the following syntactic sugar: r.x is an alias for r[1], r.y is an alias for r[2], and so on.

The following constructor can be used to create rects.

  • r = rect(…​)
    Creates a 2D axis-aligned rect. Values to initialize the rect may be optionally passed as a list of numbers, or as a previously created rect (exceeding values are discarded, while missing values are replaced with zeros). No consistency check is performed on the passed coordinates.

  • t = torect(t)
    Turn an appropriately sized table into a rect, by adding the relevant meta information to it.

examples
r = glmath.rect()              --> r = [ 0, 0, 0, 0 ]
r = glmath.rect(-1, 1, 2, 3)   --> r = [ -1, 1, 2, 3 ]
  • boolean = isrect(r)
    Check if r is a rect.

Complex numbers

A complex number z = re + i·im (where i is the square root of -1) is implemented as a table holding re and im in its array part (i.e. { re, im }).

The real and imaginary parts are Lua numbers and can be accessed through standard indexing (that is, z[1] is the real part re, and z[2] is the imaginary part im), or using the re-im syntactic sugar (z.re and z.im are aliases for z[1] and z[2], respectively).

The following constructor can be used to create complex numbers:

  • z = complex([re], [im])
    z = complex(z)
    {z1, z2, …​} = complex({re1, im1, re2, im2, …​})
    Create a complex number from its real and imaginary parts (which default to 0) or from a previously created complex number z.

  • t = tocomplex(t)
    Turn an appropriately sized table into a complex number, by adding the relevant meta information to it.

examples
z = glmath.complex()             --> z = 0 + 0i
z = glmath.complex(2)            --> z = 2 + 0i
z = glmath.complex(nil, 5)       --> z = 0 + 5i
z = glmath.complex(3, 4)         --> z = 3 + 4i
w = glmath.complex(z)            --> w = 3 + 4i
t = glmath.complex({1, 2, 3, 4}) --> t[1] = 1 + 2i, t[2] = 3 + 4i
  • boolean = iscomplex(z)
    Returns true if z is a complex number or a Lua number, false otherwise.


The complex functions and operators listed below are based on the C99 functions for the complex type (see <complex.h> or man complex(7) for more details).

Complex functions accept also real numbers (i.e. plain Lua numbers) as arguments, which they understand as complex numbers with im=0. The same holds for binary complex operators, where one of the two operands can be a real number (if both are, the standard Lua operators for numbers are obviously used).

Complex functions, also available as methods for their first argument:

  • re = creal(z)
    im = cimag(z)
    re, im = parts(z)
    |z| = cabs(z)
    |z| = norm(z)
    rad = carg(z)
    |z|2 = norm2(z)
    z/|z| = normalize(z)
    z* = conj(z)
    z1 = cproj(z)
    z-1 = inv(z)

  • ez = cexp(z)
    ln(z) = clog(z)
    z1/2 = csqrt(z)
    zw = cpow(z, w)

  • z1 = csin(z)
    z1 = ccos(z)
    z1 = ctan(z)
    z1 = casin(z)
    z1 = cacos(z)
    z1 = catan(z)

  • z1 = csinh(z)
    z1 = ccosh(z)
    z1 = ctanh(z)
    z1 = casinh(z)
    z1 = cacosh(z)
    z1 = catanh(z)


Complex operators:

  • Unary minus: z = -z1.

  • Addition: z = z1 + z2.

  • Subtraction: z = z1 - z2.

  • Multiplication: z = z1 * z2.

  • Division: z = z1 / z2.

  • Power: z = z1 ^ z2.

Basic Transforms

  • m = translate(v)
    m = translate(x , y , z)
    Returns the 4x4 translation matrix, given the vector v or its components x, y, and z.

  • m = scale(v)
    m = scale(x, [y] , [z])
    Returns the 4x4 scaling matrix, given the scaling factors x, y, and z, which may also be passed as a vector.
    If y and z are not given, they are assumed equal to x (i.e. uniform scaling by a factor x).

  • m = rotate(angle, v)
    m = rotate(angle, x , y , z)
    Return the 4x4 rotation matrix given the angle (in radians) and the direction vector v = (x, y, z).

  • m = rotate_x(angle)
    m = rotate_y(angle)
    m = rotate_z(angle)
    Return the 4x4 rotation matrix for a rotation by angle radians around the x, y or z axis, respectively.

Camera and Projections

The functions below follow the traditional OpenGL conventions, where the camera (or viewer) is in the origin, looking towards the negative z-axis, with the positive x-axis pointing to its right and the positive y-axis pointing up, and the near and far parameters represent the distance of the near and far planes from the origin along the viewing direction (i.e. they are the negated z-coordinates of the two planes).

  • m = look_at(eye, at, up)
    Returns a 4x4 matrix to transform from world coordinates to camera coordinates, given the camera position and orientation in world coordinates: eye is the camera position, at is its target point, and up is the direction from the camera to a point on the vertical above the target.

  • m = ortho(left, right, bottom, top, [near], [far])
    Returns a 4x4 ortographic projection matrix that transforms an axis-aligned box into the axis-aligned cube of side 2 centered at the origin.
    The box is bounded by the planes x=left, x=right, y=bottom, y=top, z=-near, and z=-far.
    The near and far values default to -1.0 and 1.0 respectively (2D projection).

  • m = frustum(left, right, bottom, top, near, far)
    Returns a 4x4 perspective projection matrix. The view frustum has the center of projection in the origin, its near face is the rectangle (left<x<right, bottom<y<top) in the z=-near plane, and its far face is in the z=-far plane.

  • m = perspective(fovy, aspect, near, far)
    Returns a 4x4 perspective projection matrix. The view frustum has the center of projection in the origin, a vertical field of view given by fovy (radians), and its near and far faces have the given aspect ratio (width/height), and are at z=-near and z=-far, respectively.

Data handling

This section describes additional utilities that can be used to encode data from Lua variables to binary strings and viceversa.

  • val1, …​, valN = flatten(table)
    Flattens out the given table and returns the terminal elements in the order they are found.
    Similar to Lua’s table.unpack( ), but it also unpacks any nested table. Only the array part of the table and of nested tables is considered.

  • {val1, …​, valN} = flatten_table(table)
    Same as flatten( ), but returns the values in a flat table. Unlike flatten( ), this function can be used also with very large tables.

  • size = sizeof(type)
    Returns the size in bytes of the given type.

  • data = pack(type, val1, …​, valN)
    data = pack(type, table)
    Packs the numbers val1, …​, valN, encoding them according to the given type, and returns the resulting binary string.
    The values may also be passed in a (possibly nested) table. Only the array part of the table (and of nested tables) is considered.

  • {val1, …​, valN} = unpack(type, data)
    Unpacks the binary string data, interpreting it as a sequence of values of the given type, and returns the extracted values in a flat table.
    The length of data must be a multiple of sizeof(type).

type: data types (and their corresponding C99 types)
Values: 'char' (int8_t), 'uchar' (uint8_t), 'short' (int16_t), 'ushort' (uint16_t), 'int' (int32_t), 'uint' (uint32_t), 'long' (int64_t), 'ulong' (uint64_t), 'float' (float), 'double' (double).

Host memory objects

An hostmem object encapsulates a pointer to host accessible memory [2], with methods to access it from Lua and to retrieve pointers to any of its locations in form of lightuserdata.

The memory encapsulated by an hostmem object may be either memory allocated via the glmath.malloc( ) or the glmath.aligned_alloc( ) functions, or memory obtained by other means (e.g. mapped memory or shared virtual memory) and passed to the glmath.hostmem( ) constructor.

Hostmem objects are automatically deleted at exit, but they may also be deleted manually via the glmath.free( ) function (or the corresponding method).

  • hostmem = malloc(size)
    hostmem = malloc(data)
    hostmem = malloc(type, {value1, …​, valueN})
    hostmem = malloc(type, value1, …​, valueN)
    Allocates host memory and creates an hostmem object to encapsulate it.
    malloc(size), where size is an integer, allocates size bytes of contiguous memory and initializes them to 0;
    malloc(data), where data is a binary string, allocates #data bytes of contiguous memory and initializes them with the contents of data;
    malloc(type, …​) is functionally equivalent to malloc(glmath.pack(type, …​)).

  • hostmem = aligned_alloc(alignment, size)
    hostmem = aligned_alloc(alignment, data)
    hostmem = aligned_alloc(alignment, type, {value1, …​, valueN})
    hostmem = aligned_alloc(alignment, type, value1, …​, valueN)
    Same as malloc( ), with the additional alignment parameter to control memory address alignment (rfr. aligned_alloc(3)).

  • hostmem = hostmem(size, ptr)
    hostmem = hostmem(data)
    Creates a hostmem object encapsulating user provided memory.
    Such memory may be provided in form of a lightuserdata (ptr) containing a valid pointer to size bytes of contiguous memory, or as a binary string (data).
    In both cases, care must be taken that the memory area remains valid until the hostmem object is deleted, or at least until it is accessed via its methods. In the data case, this means ensuring that data is not garbage collected during the hostmem object lifetime.
    (Note that malloc(data) and hostmem(data) differ in that the former allocates memory and copies data in it, while the latter just stores a pointer to data).

  • free(hostmem)
    hostmem:free( )
    Deletes the hostmem object. If hostmem was created with glmath.malloc( ) or glmath.aligned_alloc( ), this function also releases the encapsulated memory.

  • ptr = hostmem:ptr([offset=0], [nbytes=0])
    Returns a pointer (lightuserdata) to the location at offset bytes from the beginning of the encapsulated memory.
    Raises an error if the requested location is beyond the boundaries of the memory area, or if there are not at least nbytes of memory after it.

  • nbytes = hostmem:size([offset=0])
    nbytes = hostmem:size(ptr)
    Returns the number of bytes of memory available after offset bytes from the beginning of the encapsulated memory area, or after ptr (a lightuserdata obtained with hostmem:ptr( )).

  • data = hostmem:read([offset], [nbytes])
    {val1, …​, valN} = hostmem:read([offset], [nbytes], type)
    Reads nbytes of data starting from offset, and returns it as a binary string or as a table of primitive values.
    The offset parameter defaults to 0, and nbytes defaults to the memory size minus offset.
    hostmem:read(offset, nbytes, type) is functionally equivalent to glmath.unpack(type, hostmem:read(offset, nbytes)).

  • hostmem:write(offset, nil, data)
    hostmem:write(offset, type, val1, …​, valN)
    hostmem:write(offset, type, {value1, …​, valueN})
    Writes to the encapsulated memory area, starting from the byte at offset.
    write(offset, nil, data) writes the contents of data (a binary string);
    write(offset, type, …​) is equivalent to write(offset, nil, glmath.pack(type, …​)).

  • hostmem:copy(offset, size, srcptr)
    hostmem:copy(offset, size, srchostmem, srcoffset)
    Copies size bytes to the encapsulated memory area, starting from the byte at offset.
    copy(offset, size, srcptr), copies the size bytes pointed to by srcptr (a lightuserdata).
    copy(offset, size, srchostmem, srcoffset), copies size bytes from the memory encapsulated by srchostmem (a hostmem object), starting from the location at srcoffset.

  • hostmem:clear(offset, nbytes, [val=0])
    Clears nbytes of memory starting from offset. If the val parameter is given, the bytes are set to its value instead of 0 (val may be an integer or a character, i.e. a string of length 1).

Tracing utilities

  • trace_objects(boolean)
    Enable/disable tracing of objects creation and destruction (which by default is disabled).
    If enabled, a printf is generated whenever an object is created or deleted, indicating the object type and the value of its raw handle.

  • t = now( )
    Returns the current time in seconds (a Lua number).
    This is implemented with monotonic clock_gettime(3), if available, or with gettimeofday(3) otherwise.

  • dt = since(t)
    Returns the time in seconds (a Lua number) elapsed since the time t, previously obtained with the now( ) function.

  • mean, var, min, max = stats({number})
    Computes the mean, variance, and the minimum and maximum values for the given array of numbers.

  • dumpdata({number}, filename, [mode='w'])
    Writes the given array of numbers to the given file file (plain ascii format, two columns index-value).
    The data can then be displayed, for example, using gnuplot (gnuplot> plot "filename" using 1:2 with lines).
    mode is the same as in io.open( ).


1. This manual is written in AsciiDoc, rendered with AsciiDoctor and a CSS from the AsciiDoctor Stylesheet Factory. The PDF version is produced with AsciiDoctor-Pdf.
2. The term 'host' is here used as for the Khronos OpenCL specs, to denote the machine where the application is running, as opposed to a device such as a GPU.