1. Lua

Lua is a powerful and fast scripting language that is easy to learn. In UniPlot R2016 Lua can be used parallel with UniScript. UniPlot uses LuaJIT (http://www.luajit.org) from Mike Pall.

1.1. More Informationen

The first edition of “Programming in Lua” by Roberto Ierusalimschy, Lua.org, December 2003, ISBN 8590379817 is available online: http://www.lua.org/pil/contents.html

1.2. Short comparison of Lua and UniScript

Here is an example in UniScipt. The function finds the index of the maximum element in a vector:

// Maximum and index of a vector
def maximum(a)
    mi = 1;
    m = a[mi];

    for (i in 1:len(a)) {
        if (a[i] > m) {
            mi = i;
            m = a[i];
    return [m, mi];

To create the function, we use a UniPlot-Editor. The file must be saved with the extension .ic. The UniScript=>Save/Execute command or the function key F4 translates the function. To invoke the function, open the command window (View=>Command Window). First we create a vector with 1,000,000 random numbers in the range 0 to 1.

* r = rand(1,1e6)
* tic(); maximum(r); toc()

tic() starts a timer and toc() returns the time since the timer has been started in milliseconds.

Here is the same function in Lua.

-- Maximum and index of a vector
function maximum(a)
    local mi = 1
    local m = a[mi]

    for i = 1, #a do
        if a[i] > m then
            mi = i
            m = a[i]
    return m, mi

The function must be saved in a file with the extension .lua.

The first line is a comment. In Lua, comments start with a doublehyphen -- and run until the end of the line.

Instead of def the Lua function is created with the function keyword. In UniScript statements are enclosed in braces { ... }. Lua uses the end keyword.

function ... end
for ... do ... end
if ... then ... end

The first statement in UniScript is mi = 1; and in Lua local mi = 1.

In UniScript all variables inside a function are local variables. To create a global variable, it must be declared at the beginning of the function using the global keyword.

In Lua a local variable must be declared before using it with the keyword local. Otherwise the variable is global. See also http://lua-users.org/wiki/LocalByDefault.

To compile the Lua function press F4 in the editor. To execute the function open the the command window. To switch into the Lua mode type in .lua.


Now you can execute the following statements:

> a = {}; for i=1,1e6 do a[i] = math.random() end
> up = require"uniplot"
> up.tic(); maximum(a); print(up.toc())

The first command creates a Lua table with 1 million elements. The random() function from the Lua math library will create a random number.

The second statement loads the uniplot library for the functions tic() and toc(). They use the Windows QueryPerformanceCounter function to measure the execution time.

The Lua function takes approx. one millisecond. The UniScript function takes approx. 50 milliseconds. The reasons are: 1.) LuaJIT is a Just-In-Time compiler, 2.) UniScript is an interpreter.

In practice, UniScript will call a C function to calculate the maximum. Exit the Lua command window with the exit command. In the UniScript command window the maxi function can be invoked. This function is even a bit faster than the Lua function.

* a = rand(1e6,1);
* tic(); maxi(a); toc()

1.3. UniScript Interface

The r = us.call(us_func_name, p1, ...) function is used to call an UniScript function. The interface is loaded from the lua_uniscript.dll dll. Example:

us = require "lua-uniscript"   -- load lua-uniscript.dll
m = us.call("sin", 1)

If a UniScript function returns a scalar number, it will be converted to a Lua number. In all other cases the UniScript value will be converted to a Lua userdata element.

x = us.call("linspace", 0, 2*math.pi, 1e5)
matrix: 0x22e70660

x is a UniScript vector with 100,000 points.

y = us.call("sin", x)
us.call("plot", x, y)

Normally us.call() will not be invoked directly. A wrapper function is used instead. Here are some examples of the uniplot module:

-- uniplot.lua

local us = require "lua-uniscript"
local mat = require "uniplot.matrix"

local u = {}

u.abs = function(a1)
    return mat:new(us.call("abs", a1))

u.acos = function(a1)
    return mat:new(us.call("acos", a1))

u.acosh = function(a1)
    return mat:new(us.call("acosh", a1))

return u

With the following two packages

up = require"uniplot"
mat = require"uniplot.matrix"

the following UniScript operators can be executed:

UniScript Lua Comment
a + b a + b or mat.add(a, b) The matrices must have the same size or must be scalars.
a - b a - b or mat.sub(a, b) Subtraction.
a * b a * b or mat.mul(a, b) Matrix multiplication
a .* b mat.emul(a, b) Multiplication element wise
a / b a / b or mat.div(a, b)  
a ./ b mat.ediv(a, b) Disision element wise
a \ b    
a' a:trans() Transponse.
a.' a:etrans()  
nr(a) a:nr() or mat.nr(a) Number of rows.
nc(a) a:nc() or mat.nc(a) Number of columns.
len(a) #a or a:len() or mat.len(a) Number of elements of a vector.
a^-1 or inv(a) a^-1 or a:inv() or mat.inv(a) Inverse of a matrix.
[1,2,3] mat.matrix{1,2,3} Row vector
[1;2;3] mat.matrix({1,2,3}):trans() Column vector.
[1,2;3,4] up.reshape(mat.matrix{1,2,3,4}, 2, 2):trans() Matrix
[a, b] mat.hcat(a,b) Concatenate matrices horizontally
[a; b] mat.vcat(a,b) Concatenate matrices vertical
a < b, <= == != > >= mat.lt(a, b), le, eq, ne, gt, ge Compare operators for matrices and vectors.
a & b, a | b, a@b, ~a, a << b, a >> b mat.band(a, b), bor, xor, not, shl, shr Bit wise and, or, exclusiv or, not, shift left, shift right
1:10, 1:0.5:3, 3:1 mat.range(1, 10), mat.range(1,0.5,3), mat.range(3, 1) Sequence [1, 2, .. 10], [1, 1.5, 2, 2.5, 3], [3, 2, 1]
b = a[i;j] b = a:rowcol(i, j)  
a[i;], a[;j] a:row(i), a:col(j)  
a[:] reshape(a, 1, #a)  
c = 1+3i c = complex(1, 3) Create complex numbers and matrices.

1.4. Lua Debugger

A Lua-Debugger will be available in one of the next releases.

1.5. Remarks

  • The LuaJIT version is 2.1-beta, 2016-01-18 with -DLUAJIT_ENABLE_LUA52COMPAT enabled. The DLL luajit.dll is compiled using the Microsoft Visual Studio 2015 kompiliert with the C-Runtime-Library msvcr120.dll.

    The LuaJIT DLL can be replaced by an owner build DLL.