Sysquake Pro – Table of Contents

Sysquake for LaTeX – Table of Contents

# LME Tutorial

This chapter introduces LME(TM) (Lightweight Math Engine), the interpreter for numeric computing used by Sysquake, and shows you how to perform basic computations. It supposes you can type commands to a command-line interface. You are invited to type the examples as you read this tutorial and to experiment on your own. For a more systematic description of LME, please consult the LME Reference chapter.

In the examples below, we assume that LME displays a prompt `>`.
This is not the case for all applications. You should never type it yourself.
Enter what follows the prompt on the same line, hit the Return key (or tap the Eval
or Execute button), and observe the result.

## Simple operations

LME interprets what you type at the command prompt and displays the result unless you end the command with a semicolon. Simple expressions follow the syntactic rules of many programming languages.

> 2+3*4 ans = 14 > 2+3/4 ans = 2.75

As you can see, the evaluation order follows the usual rules which state that the multiplication (denoted with a star) and division (slash) have a higher priority than the addition and subtraction. You can change this order with parenthesis:

> (2+3)*4 ans = 20

The result of expressions is automatically assigned to variable `ans`
(more about variables later), which you can reuse in the next expression:

> 3*ans ans = 60

Power is represented by the `^` symbol:

> 2^5 ans = 32

LME has many mathematical functions. Trigonometric functions assume that angles
are expressed in radians, and `sqrt` denotes the square root.

> sin(pi/4) * sqrt(2) ans = 1

## Complex Numbers

In many computer languages, the square root is defined only for nonnegative
arguments. However, it is extremely useful to extend the set of numbers to remove
this limitation. One defines `j`. You can use it like any
function, or stick an `i` or `j` after a number:

> 2+3*j ans = 2+3j > 3j+2 ans = 2+3j

Many functions accept complex numbers as argument, and return a complex result when the input requires it even if it is real:

> sqrt(-2) ans = 0+1.4142i > exp(3+2j) ans = -8.3585+18.2637j > log(-8.3585+18.2637j) ans = 3+2j

To get the real or imaginary part of a complex number, use the functions
`real` or `imag`, respectively:

> real(2+3j) ans = 2 > imag(2+3j) ans = 3

Complex numbers can be seen as vectors in a plane. Then addition and subtraction of complex numbers correspond to the same operations applied to the vectors. The absolute value of a complex number, also called its magnitude, is the length of the vector:

> abs(3+4j) ans = 5 > sqrt(3^2+4^2) ans = 5

The argument of a complex number is the angle between the x axis ("real axis")
and the vector, counterclockwise. It is calculated by the `angle` function.

> angle(2+3j) ans = 0.9828

The last function specific to complex numbers we will mention here is
`conj`, which calculates the conjugate of a complex number. The conjugate
is simply the original number where the sign of the imaginary part is changed.

> conj(2+3j) ans = 2-3j

Real numbers are also complex numbers, with a null imaginary part; hence

> abs(3) ans = 3 > conj(3) ans = 3 > angle(3) ans = 0 > angle(-3) ans = 3.1416

## Vectors and Matrices

LME manipulates vectors and matrices as easily as scalars. To define a matrix, enclose its contents in square brackets and use commas to separate elements on the same row and semicolons to separate the rows themselves:

> [1,2;5,3] ans = 1 2 5 3

Column vectors are matrices with one column, and row vectors are matrices with one row. You can also use the colon operator to build a row vector by specifying the start and end values, and optionally the step value. Note that the end value is included only if the range is a multiple of the step. Negative steps are allowed.

> 1:5 ans = 1 2 3 4 5 > 0:0.2:1 ans = 0 0.2 0.4 0.6 0.8 1 > 0:-0.3:1 ans = 0 -0.3 -0.6 -0.9

There are functions to create special matrices. The `zeros`,
`ones`, `rand`, and `randn`
functions create matrices full of zeros, ones, random numbers uniformly
distributed between 0 and 1, and random numbers normally distributed with
a mean of 0 and a standard deviation of 1, respectively. The `eye`
function creates an identity matrix, i.e. a matrix with ones on the main
diagonal and zeros elsewhere. All of these functions can take one scalar
argument n to create a square n-by-n matrix, or two arguments m and n to
create an m-by-n matrix.

> zeros(3) ans = 0 0 0 0 0 0 0 0 0 > ones(2,3) ans = 1 1 1 1 1 1 > rand(2) ans = 0.1386 0.9274 0.3912 0.8219 > randn(2) ans = 0.2931 1.2931 -2.3011 0.9841 > eye(3) ans = 1 0 0 0 1 0 0 0 1 > eye(2,3) ans = 1 0 0 0 1 0

You can use most scalar functions with matrices; functions are applied to each element.

> sin([1;2]) ans = 0.8415 0.9093

There are also functions which are specific to matrices. For example, `det`
calculates the determinant of a square matrix:

> det([1,2;5,3]) ans = -7

Arithmetic operations can also be applied to matrices, with their usual mathematical
behavior. Additions and subtractions are performed on each element. The multiplication
symbol `*` is used for the product of two matrices or a scalar and a matrix.

> [1,2;3,4] * [2;7] ans = 16 34

The division symbol `/` denotes the multiplication by the inverse of the
right argument (which must be a square matrix). To multiply by the inverse of the left
argument, use the symbol `\`. This is handy to solve a set of linear equations.
For example, to find the values of

> [1,2;3,4] \ [2;7] ans = 3 -0.5

Hence `inv` function, which return the inverse of its argument.
It is sometimes useful to multiply or divide matrices element-wise. The `.*`,
`./` and `.\` operators do exactly that. Note that the
`+` and `-` operators do not need special dot versions,
because they perform element-wise anyway.

> [1,2;3,4] * [2,1;5,3] ans = 12 7 26 15 > [1,2;3,4] .* [2,1;5,3] ans = 2 2 15 12

Some functions change the order of elements. The transpose operator (tick) reverses the columns and the rows:

> [1,2;3,4;5,6]' ans = 1 3 5 2 4 6

When applied to complex matrices, the complex conjugate transpose is obtained.
Use dot-tick if you just want to reverse the rows and columns. The
`flipud` function flips a matrix upside-down, and `fliplr`
flips a matrix left-right.

> flipud([1,2;3,4]) ans = 3 4 1 2 > fliplr([1,2;3,4]) ans = 2 1 4 3

To sort the elements of each column of a matrix, or the elements of a row vector,
use the `sort` function:

> sort([2,4,8,7,1,3]) ans = 1 2 3 4 7 8

To get the size of a matrix, you can use the `size` function, which gives
you both the number of rows and the number of columns unless you specify which of them
you want in the optional second argument:

> size(rand(13,17)) ans = 13 17 > size(rand(13,17), 1) ans = 13 > size(rand(13,17), 2) ans = 17

## Polynomials

LME handles mostly numeric values. Therefore, it cannot differentiate functions
like `[2,3,-5]`, and `[2,0,0,0,3,0]`.

Adding two polynomials would be like adding the coefficient vectors if they had
the same size; in the general case, however, you had better use the function
`addpol`, which can also be used for subtraction:

> addpol([1,2],[3,7]) ans = 4 9 > addpol([1,2],[2,4,5]) ans = 2 5 7 > addpol([1,2],-[2,4,5]) ans = -2 -3 -3

Multiplication of polynomials corresponds to convolution (no need to understand what it means here) of the coefficient vectors.

> conv([1,2],[2,4,5]) ans = 2 8 13 10

Hence

## Strings

You type strings by delimiting them with single quotes:

> 'Hello, World!' ans = Hello, World!

If you want single quotes in a string, double them:

> 'Easy, isn''t it?' ans = Easy, isn't it?

Some control characters have a special representation. For example, the line feed, used in LME as an end-of-line character, is \n:

> 'Hello,\nWorld!' ans = Hello, World!

Strings are actually matrices of characters. You can use commas and semicolons to build larger strings:

> ['a','bc';'de','f'] ans = abc def

## Variables

You can store the result of an expression into what is called a variable. You can have as many variables as you want and the memory permits. Each variable has a name to retrieve the value it contains. You can change the value of a variable as often as you want.

> a = 3; > a + 5 ans = 8 > a = 4; > a + 5 ans = 9

Note that a command terminated by a semicolon does not display its result. To
see the result, remove the semicolon, or use a comma if you have several commands
on the same line. Implicit assignment to variable `ans` is not performed
when you assign to another variable or when you just display the contents of a
variable.

> a = 3 a = 3 > a = 7, b = 3 + 2 * a a = 7 b = 17

## Loops and Conditional Execution

To repeat the execution of some commands, you can use either a `for/end`
block or a `while/end` block. With `for`, you use a variable
as a counter:

> for i=1:3;i,end i = 1 i = 2 i = 3

With `while`, the commands are repeated as long as some expression is
true:

> i = 1; while i < 10; i = 2 * i, end i = 2 i = 4 i = 8

You can choose to execute some commands only if a condition holds true :

> if 2 < 3;'ok',else;'amazing...',end ans = ok

## Functions

LME permits you to extend its set of functions with your own. This is convenient not only when you want to perform the same computation on different values, but also to make you code clearer by dividing the whole task in smaller blocks and giving names to them. To define a new function, you have to write its code in a file; you cannot do it from the command line. In Sysquake, put them in a function block.

Functions begin with a header which specifies its name, its input arguments (parameters which are provided by the calling expression) and its output arguments (result of the function). The input and output arguments are optional. The function header is followed by the code which is executed when the function is called. This code can use arguments like any other variables.

We will first define a function without any argument, which just displays a magic square, the sum of each line, and the sum of each column:

function magicsum3 magic_3 = magic(3) sum_of_each_line = sum(magic_3, 2) sum_of_each_column = sum(magic_3, 1)

You can call the function just by typing its name in the command line:

> magicsum3 magic_3 = 8 1 6 3 5 7 4 9 2 sum_of_each_line = 15 15 15 sum_of_each_column = 15 15 15

This function is limited to a single size. For more generality, let us add an input argument:

function magicsum(n) magc = magic(n) sum_of_each_line = sum(magc, 2) sum_of_each_column = sum(magc, 1)

When you call this function, add an argument:

> magicsum(2) magc = 1 3 4 2 sum_of_each_line = 4 6 sum_of_each_column = 5 5

Note that since there is no 2-by-2 magic square, `magic(2)` gives
something else... Finally, let us define a function which returns the sum of each
line and the sum of each column:

function (sum_of_each_line, sum_of_each_column) = magicSum(n) magc = magic(n); sum_of_each_line = sum(magc, 2); sum_of_each_column = sum(magc, 1);

Since we can obtain the result by other means, we have added semicolons after each statement to suppress any output. Note the uppercase S in the function name: for LME, this function is different from the previous one. To retrieve the results, use the same syntax:

> (sl, sc) = magicSum(3) sl = 15 15 15 sc = 15 15 15

You do not have to retrieve all the output arguments. To get only the first one, just type

> sl = magicSum(3) sl = 15 15 15

When you retrieve only one output argument, you can use it directly in an expression:

> magicSum(3) + 3 ans = 18 18 18

One of the important benefits of defining function is that the variables have
a limited scope. Using a variable inside the function does not make it available
from the outside; thus, you can use common names (such as `x`
and `y`) without worrying about whether they are used in some other
part of your whole program. For instance, let us use one of the variables of
`magicSum`:

> magc = 77 magc = 77 > magicSum(3) + magc ans = 92 92 92 > magc magc = 77

## Local and Global Variables

When a value is assigned to a variable which has never been referenced, a new variable is created. It is visible only in the current context: the base workspace for assignments made from the command-line interface, or the current function invocation for functions. The variable is discarded when the function returns to its caller.

Variables can also be declared to be global, i.e. to survive the end
of the function and to support sharing among several functions and the
base workspace. Global variables are declared with keyword `global`:

global x global y z

A global variable is unique if its name is unique, even if it is declared in several functions.

In the following example, we define functions which implement a queue
which contains scalar numbers. The queue is stored in a global variable named
`QUEUE`. Elements are added at the front of the vector with
function `queueput`, and retrieved from the end of the vector
with function `queueget`.

function queueput(x) global QUEUE; QUEUE = [x, QUEUE]; function x = queueget global QUEUE; x = QUEUE(end); QUEUE(end) = [];

Both functions must declare `QUEUE` as global; otherwise,
the variable would be local, even if there exists also a global variable
defined elsewhere. The first time a global variable is defined, its value
is set to the empty matrix `[]`. In our case, there is no need
to initialized it to another value.

Here is how these functions can be used.

> queueput(1); > queueget ans = 1 > queueput(123); > queueput(2+3j); > queueget ans = 123 > queueget ans = 2 + 3j

To observe the value of `QUEUE` from the command-line
interface, `QUEUE` must be declared global there. If a
local variable `QUEUE` already exists, it is discarded.

> global QUEUE > QUEUE QUEUE = [] > queueput(25); > queueput(17); > QUEUE QUEUE = 17 25