numEclipse - An Eclipse based workbench for

Scientific Computing

Home

Downloads

Documents

Links

Language Basics

In the previous chapter we learnt about the workbench. We looked at how to write and execute a program in m-script and java. In this chapter, we will focus on the m-script language specification. This scripting language is a subset of MATLAB's m-language and a mix of octave's scripting language. This chapter is intended for anybody how wish to write programs using the m-script. Here, we will cover the program structure, data structures, expressions, control flow commands, functions and procedures. 

3.1 Program Structure

numEclipse can be used in two modes; interactive and programming. In the interactive mode we type the commands on the interpreter window and execute them as we go from one command to another. This mode is useful when you are experimenting with your algorithms or you are using the tool as a sophisticated scientific calculator. In the programming mode we would write a set of commands / statements in a file and execute all the commands in the file together. The commands / statements in both modes are almost same, as they are based on same language specification. In interactive mode you have some additional commands specific for the interactive environment which is not applicable to programming environment. We decided to keep the language case sensitive for a better user experience.

Most programming languages have a program name, program start command and end command. numEclipse does not have such notion. numEclipse program is just a collection of commands / statements. Most compilation errors are caused by not declaring or initializing the variables. In numEclipse, there is no need to declare or initialize a variable. Even the size of an array is not required to be initialized, arrays and matrices can grow at runtime. This gives the user enormous power and flexibility. Don’t forget that dynamically changing the matrix size has some computational cost. To get the better performance out of this system it is advisable to initialize the matrix to the desired size, if possible.

 

3.2 Data Types

The most important data type supported by m-script is matrix. At this point, we only support one- and two- dimensional matrices. A matrix element could be either real, complex, string, boolean, cell or structure. So all these data types are supported within m-script. However, there are some limitations, as nested data types like structure within a structure or cell within a cell is not supported. Similarly, multi-dimensional array are not supported either. But, we do plan to overcome these deficiencies in future releases.

 

3.2.1 Real Data Type

Real data type is a double precision floating point number type. It is equivalent to java primitive "double". The maximum value of a real number is realmax, 1.7977e+308, the minimum value is realmin, 4.9000e-324 and the precision of the real number is eps, 2.2204e-016.

 

>> x = 3.5

x =

3.5000

 

>> y = 2.7

y =

2.7000

 

>> z = x + y

z =

6.2000

 

>> realmin

realmin =

4.9000E-324

 

>> realmax

realmax =

1.7977E308

 

>> eps

eps =

2.2204E-016

 

3.2.2 Complex Data Type

A pair of real numbers forms a complex number. The first part is called the real part and the second part is called the imaginary part. There is no java equivalent for this data type.

 

>> z1 = 2 + 2j

z1 = 2.0000 + 2.0000i

 

>> z2 = -1 + 3i

z2 = -1.0000 + 3.0000i

 

>> z3 = z1 * z2

z3 =

-8.0000 + 4.0000i

 

You would notice in the above example that we use both "i" and "j" to represent the imaginary part.

3.2.3 Boolean Data Type

The Boolean data type corresponds to the java boolean primitive type. A boolean type variable is limited to only true and false values. An expression evaluating into a number greater than zero will be treated as a true boolean value and a zero value expression will be treated as false.

 

>> b = 2 > 1

b =

true

3.2.4 String Type

The String data type is equivalent to java String data type. numEclipse uses both single and double quotes to enclose strings unlike MATLAB which uses single quotes only.

 

>> s1 = 'John'

s1 =

Ali

 

>> s2 = 'Hello'

s2 =

Hello

 

>> s = s2 + ' ' + s1

s =

Hello John

 

3.2.5 Matrix Data Type

This is the key data type of this language. There is no java equivalent for this data type. A matrix with only one column represents a mathematical entity vector and a matrix with one row represents a row vector. A matrix is basically a two dimensional array of complex numbers. It also covers real matrices since a complex number without an imaginary part is essentially a real number.

 

>> A = [1 2 3; 4 5 6; 7 8 9]

A =

1.0000   2.0000   3.0000

4.0000   5.0000   6.0000

7.0000   8.0000   9.0000

 

>> B = [-9 7 4

2 -6 4

1 3 9]

B =

-9.0000   7.0000   4.0000

2.0000    -6.0000  4.0000

1.0000    3.0000    9.0000

 

In the first matrix A we use semicolons to separate rows where as in matrix B we just use a newline to indicate the start of new row. In above example, we used spaces to separate the elements in a row. You can also use comma to avoid any ambiguity.

3.3 Expression

numEclipse scripting provides everything required to define a very complicated mathematical expression as discussed in the following sections.

3.3.1 Range Expression

A range expression provides a short cut notation to define a vector. Say we want to define a vector containing positive integers ranging from 1 to 10, using this notation we could define it as follows.

 

>> m = 1:10

m =

1.0000   2.0000   3.0000   4.0000   5.0000   6.0000   7.0000   8.0000   9.0000    10.0000

 

Now, if we define a similar vector starting from 10 and ending into 50 but with the incremental steps of 10, it could be defined as follows.

 

>> n = 1:10:50

n =

1.0000    11.0000   21.0000    31.0000   41.0000

 

This saves us from listing all the vector elements. Similarly, we could define vectors with descending values using negative incremental steps.

 

>> u = 10:-2:1

u =

10.0000    8.0000   6.0000   4.0000   2.0000

 

3.3.2 Conditional Expression

Conditional expression is the other name for Boolean expression. A boolean expression evaluates to either a true or a false value. Unlike MATLAB, numEclipse does have a real boolean type but it still supports the MATLAB’s notion of a boolean. A zero is treated as ‘false’ and a positive number is treated as ‘true’. There could be three types of conditional expressions.

 

Pure Boolean Expression:

A pure Boolean expression is composed of boolean primitives and logical operations, e.g.

 

>> true && false

ans =

false

 

>> ~true

ans =

false

 

>> ~false

ans =

true

 

numEclipse supports following boolean operators.

NOT ~  
AND &&, & both notations stand for short circuit AND
OR ||, | both notations stand for short circuit OR

 

Pure Relational Expression:

A pure relational expression is composed of numbers (scalar, vector, matrix or complex) and relation operators, e.g.

 

>> 3 > 1

ans =

true

 

>> A = rand(2)

A =

0.7242   0.2868

0.9793   0.9371

 

>> A > 0

ans =

1.0000   1.0000

1.0000   1.0000

 

numEclipse supports following relational operators.

less than <
greater than >
less than and equal to <=
greater than and equal to >=
equal to ==
not equal to <>, ~=, !=

 

Conditional Expression

A conditional expression could be a composition of above two types of expression, e.g.

 

>> A = rand(2)

A =

0.7242   0.2868

0.9793   0.9373

 

>> A > 0

ans =

1.0000   1.0000

1.0000   1.0000

 

>> z = 1 - i

z =

1.0000  i

 

>> A > 0 | z > 1

ans =

1.0000   1.0000

1.0000   1.0000

 

3.3.3 Numerical Expression

numEclipse allows defining any mathematically correct numeric expression using the data types and operations defined earlier.

 

>> A

A =

0.7242   0.2868

0.9793   0.9373

 

>> z

z =

1.0000 - i

 

>> b = (A + 1) /2 - z ^ 2

b =

0.8621 + 2.0000i   0.6434 + 2.0000i

0.9896 + 2.0000i   0.9687 + 2.0000i

 

numEclipse supports following arithmetic operators.

plus +
minus -
uniary minus -
multiplication *
element-wise multiplication .*
right division /
element-wise right division ./
left division \
element-wise left division .\
power ^
element-wise power .^

Above operators could be used with any data type where they are mathematically correct.

 

3.4 Assignment Statement

A programming language means nothing without statements. It could be divided into two groups; simple statements and compound statements. numEclipse has only one simple statement i.e. assignment statement. It looks like the following structure.

            <variable name> = <expression>

“=” is the assignment operator. This statement evaluates the expression and assigns the resulting value to the variable named on the left hand side. The left hand side or lvalue must be a valid identifier. Identifier naming convention is same as in java. There is no need to declare a variable before assigning a value. numEclipse automatically determines the data type from the right hand side (or rvalue) or the expression type. The type of a variable could change as we assign a new value of different type to an existing variable.

 

>> X = 1.0

X =

1.0000

 

>> Y = [1 2 3; 4 5 6]

Y =

1.0000   2.0000   3.0000

4.0000   5.0000   6.0000

 

>> S = 'Hello World'

S =

Hello World

 

>> B = 1 < 2

B =

true

 

If a simple assignment is ended with a semi-colon then the interpreter will not report the value of the right hand side expression on the screen.

A matrix assignment involves assigning an element of an existing matrix to a value. In case of a column or row vector, the assignment will be as follows.

            <variable name> (<expression>) = expression

The expression within parenthesis on the left hand side is an index value so it should always evaluate to an integer value respecting the bounds of the matrix.

In case of a two dimensional matrix, the assignment will look like as follows.

<variable name> (<expression>, <expression>) = expression

The first index in the parenthesis determines the row number and the second index determines the column number of the matrix element.

 

>> A = rand(3)

A =

0.8467   0.0952   0.2836

0.9565   0.3782   0.5011

0.7280   0.2052   0.6668

 

>> A(2, 3) = 1.5

A =

0.8467   0.0952   0.2836

0.9565   0.3782   1.5000

0.7280   0.2052   0.6668

 

numEclipse functions could return one or more variables so the syntax for assigning single or multiple return values is shown as follows.

 

Single Assignment

>> x = min([1 2 3]])

x =

1.0000

 

>> x = max([1 2 3])

x =

3.0000

 

Multiple Assignment

>> [k t b c] = KTBC(3)

k =

2.0000   -1.0000   0.0000

-1.0000   2.0000   -1.0000

0.0000   -1.0000   2.0000

 

t =

1.0000   -1.0000   0.0000

-1.0000   2.0000  -1.0000

0.0000   -1.0000   2.0000

 

b =

1.0000   -1.0000   0.0000

-1.0000  2.0000    -1.0000

0.0000   -1.0000   1.0000

 

c =

2.0000   -1.0000   -1.0000

-1.0000  2.0000    -1.0000

-1.0000  -1.0000   2.0000

 

3.5 Control-Flow Statement

numEclipse supports following flow control statements: for, while, if, switch, continue, break and return. These statements are described in the following sections.

3.5.1 For Loop

For loop is a compound statement. It is a repetitive statement since it allows a group of statements to be executed a number of times. The structure of this statement type is a follows

 

for <identifier> = <range expression>

      <statement>

      <statement>

               .

               .

      <statement>

end

 

Here for and end are the keywords and “=” is an operator. “*” indicates that there could be zero or more statements within a for loop.

 

>> x = 0;

 

>> for i = 1 : 10

     x = x + 1;

end;

 

>> x

x =

10

 

In the above example variable x is assigned a value “0”. The for loop is repeated 10 times and at each iteration x is incremented by 1.

 

3.5.2 While Loop

While loop is also a compound statement and it is repetitive in nature. The difference between a for and while loop is that the for loop executes statements for a fixed number of time whereas while loop executes all grouped statements until a condition is satisfied. The structure of a while statement is as follows.

 

while <conditional expression>

      <statement>

      <statement>

               .

               .

      <statement>

end

 

Here while and end are keywords. In this statement the conditional expression is evaluated on the beginning of each iteration, if the conditional expression evaluates to true then the enclosed statements are executed otherwise the loop ends.

 

>> y = [0 0 0];

 

>> i = 1;

 

>> while x > 0

     y(i) = x;

     i = i + 1;

     x = x - 1;

end;

 

>> x

x =

0.0000

 

>> y

y =

3.0000   2.0000   1.0000

 

In this example three statements are executed until the condition x > 0 is satisfied.

3.5.3 If Statement

If statement is another compound statement. It consists of a conditional expression and one or more groups of statements. If the conditional expression evaluates to true then first group of statements are executed otherwise second group of statements are executed, if present.

 

if <conditional expression>

      <statement>

               .

               .

      <statement>

elseif <conditional expression>

      <statement>

               .

               .

      <statement>

elseif  <conditional expression>

      <statement>

               .

               .

      <statement>

else

      <statement>

               .

               .

      <statement>

end

 

In the above structure if, elseif, else and end are keywords. There could be zero or more parts elseif sections in a if statement. There could be zero or one else section in a if statement.

 

>> x = 1;

 

>> y = 2;

 

>> if x > 1

         y = y + 1;

elseif

         y = y - 1;

else

        y = 0;

end;

 

>> y

y =

1.0000

 

3.5.4 Switch Statement

Switch statement is helpful when you have a lot of elseif statements within a if statement. It switches among several cases based on an expression, as shown in the following syntax diagram.

 

switch <switch expression>

case <case expression>

      <statement>

               .

               .

      <statement>

case <case expression>

      <statement>

               .

               .

      <statement>

otherwise

               .

               .

case <case expression>

      <statement>

               .

               .

      <statement>

end

 

The switch expression should be either a string or a scalar value. The case expression should evaluate to the same data type as switch expression.

 

>> money = 10;

 

>> switch money

case 1

  cents = cents + 1;

case 5

  nickle = nickle + 1;

case 10

  dime = dime + 1;

case 25

  quarter = quarter + 1;

case 100

  dollars = dollars + 1;

otherwise

  disp('invalid amount');

end;

 

>> dime

dime =

1.0000

 

Unlike C or Java, you do not need to use break statement only first matching case is executed.

3.5.5 Continue

Continue statement moves the control to the next step of the for or while loop.

 

>> sum = 0;

 

>> for i = 1 : 100

sum = sum + 1;

end;

 

>> sum

sum =

100.0000

 

>> sum = 0;

 

>> for i = 1 : 100

if rem(i, 2) == 0

   continue;

end;

sum = sum + 1;

end;

 

>> sum

sum =

50.0000

 

Above example shows how continue statement skips an iteration on condition rem(i, 2) == 0.

3.5.6 Break

Break statement ends the execution of a for or while loop.

 

>> sum = 0;

 

>> for i = 1 : 100

if i == 50

   break;

end;

sum = sum + 1;

end;

 

>> sum

sum =

49

 

Above example shows how the break statement ends the execution of for loop on condition i == 50.

 

3.5.7 Return

Return statement is used in a function. This statement moves the control back to the caller program. Here is an example function.

 

function mat = myrandom(n)

if n < 1

   return;

else

   mat = rand(n);

end;

 

The above function returns the control back to the caller program if the input argument is less than 1. Here is the example.

 

>> x = myrandom(3)

x =

0.2660   0.3629   0.6100

0.4861   0.8637   0.5179

0.3443   0.1870   0.7771

 

>> x = myrandom(1)

x =

0.9397

 

>> x = myrandom(0)

 

>>

 

3.6 Function

numEclipse allows you to define your own functions. Here is the syntax definition of a function.

 

function identifier = name (argument1, argument2, ...)

      <statement>

               .

               .

      <statement>

end

Or

function [identifier1, identifier2, ...] = name (argument1, argument2, ...)

      <statement>

               .

               .

      <statement>

end

 

The second syntax definition shows that a function can return more than one values in an array. The following code shows the examples of the functions.

 

function y = variance(x)

n = length(x);

xbar = mean(x);

sum = 0;

for i = 1 : n

   sum = sum + (x(i) - xbar)^2;

end;

y = sum / n;

y = sqrt(y);

 

function [K, T, B, C] = KTBC(n)

% Create the four special matrices assuming n > 1

K = toeplitz([2 -1 zeros(1, n-2)]);

T = K; T(1, 1) = 1;

B = K; B(1, 1) = 1; B(n, n) = 1;

C = K; C(1, n) = -1; C(n, 1) = -1;

 

The following diagram shows how to call these functions.

 

>> x = 1:10;

 

>> var = variance(x)

var =

2.8723

 

>> [k t b c] = KTBC(2)

k =

2.0000   -1.0000

-1.0000   2.0000

 

t =

1.0000   -1.0000

-1.0000   2.0000

 

b =

1.0000   -1.0000

-1.0000   1.0000

 

c =

2.0000   -1.0000

-1.0000   2.0000

 

3.7 Procedure

A procedure is same as a function except it does not return any value. The syntax definition for a procedure is shown below.

 

function name (argument1, argument2, ...)

      <statement>

               .

               .

      <statement>

end

 

Here is an example for a procedure.

 

function proc(x)

    plot(1:length(x), x);

end;

 

 

In the following, we show how to call a procedure.

 

>> proc((1:10).^2)

 

3.8 Structure Data Type

Structure is a composite data type. It is very similar to struct in C language. Unlike a matrix, a structure can contain data elements of various types. Elements / fields of a structure are named rather than indexed. The following example shows how to create a structure.

 

>> employee.name = 'John';

 

>> employee.id = 123;

 

>> employee.salary = 3000;

 

>> employee.pref = [10 20; 30 40];

 

>> employee

employee =

 

perf :

10.0000   20.0000

30.0000   40.0000

 

name : John

id : 123.0000

salary : 3000.0000

 

In the above example, we use the assignment to create a structure fields. There is no need to declare the structure. The following example shows the use of struct function to create a structure variable.

 

>> emp = struct('name', 'John', 'id', 123, 'salary', 3000)

emp =

 

name : John

id : 123.0000

salary : 3000.0000

 

This function takes an even number of arguments as a sequence of field name and value pairs.

              struct('name1', value1, 'name2', value2, ...)

Note that the name of a field is provided as a string.

The following example shows how to access the value of a structure field.

 

>> emp.name = 'John';

 

>> emp.id = 123;

 

>> emp.salary = 3000;

 

>> emp.pref = [10 20; 30 40];

 

>> x = emp.salary

x =

3000.0000

 

>> s = emp.name

s =

John

 

Similarly, accessing the value of a field from a structure array is shown below.

 

>> emp(2).name = 'Peter';

 

>> emp(2)id = 456;

 

>> emp(2).salary = 2500;

 

>> emp(2).perf = [1 2; 3 4];

 

>> name = emp(2).name

name =

Peter

 

>> sal = emp(1).salary

sal =

3000.0000

 

>> x = emp(2).perf(2,2)

x =

4.0000

 

In the above example, we also show how to get a matrix element from a matrix field value of a structure array.

Unlike MATLAB, there are no add or remove functions available in numEclipse. You can add a field as shown in above example. There is no method available to remove a field. The implementation of structure is non-strict, i.e., each structure in an array could have entirely different set of fields.

The following example shows how to pass a field value to a function.

 

>> emp.perf

ans =

10.0000   20.0000

30.0000   40.0000

 

>> y = sum(emp.perf)

y =

40.0000   60.0000

 

Here, we show a function which takes an structure array as an input argument.

 

function y = TotalSalary(x)

% x - input argument    Structure array of employees

% y - output argument   Total salary of all employees

n = length(x);

y = 0;

for i = 1 : n

    y = y + x(i).salary;

end;

 

In the following, we show the call to this function.

 

>> emp

emp =

 

Index(1)

perf :

10.0000   20.0000

30.0000   40.0000

 

name : John

id : 123.0000

salary : 3000.0000

 

Index(2)

perf :

1.0000   2.0000

3.0000   4.0000

 

name : Peter

id : 458.0000

salary : 2500.0000

 

>> TotalSalary(emp)

ans =

5500.0000

 

Unlike MATLAB, numEclipse does not support nested structures.

 

3.9 Cell Data Type

Cell array is an another composite data type. It is very similar to structure array except the way it organizes the data. In a cell array each element is a cell which can contain data of any other type. A cell array can be created using a function as shown in the following example.

 

>> c = cell(2,2);

 

>> c(1, 1) = {'Hello World'};

 

>> c(2, 1) = {2};

 

>> c(2, 2) = {1 + 2i};

 

>> c

c =

 

Cell(1, 1)

Hello World

 

Cell(1, 2)

2.0000

 

Cell(2, 1)

1.0000   2.0000

 

Cell(2, 2)

1.0000 + 2.0000i

 

 

There is no need to use a function, a cell can be created just by using assignment statement. Keep in mind that a cell is always defined in a curly bracket.

 

>> ce = {[3.13   2.71]}

ce =

 

3.1300   2.7100

 

Obtaining data from a cell element is shown in the following example.

 

>> c

c =

 

Cell(1, 1)

Hello World

 

Cell(1, 2)

2.0000

 

Cell(2, 1)

1.0000   2.0000   3.0000

 

Cell(2, 2)

1.0000 + 2.0000i

 

>> x = c{2, 2}

x =

1.0000 + 2.0000i

 

A cell array cannot be nested in another cell but it can contain structure array. Here is an example.

 

>> c(1,2) = struct('name', 'John', 'id', 123, 'salary', 3000)

c =

 

Cell(1, 1)

Hello World

 

C(1, 2)

 

name : John

id : 123.0000

salary : 3000

 

 

Cell(2, 1)

1.0000   2.0000   3.0000

 

Cell(2, 2)

1.0000 + 2.0000i

 

Cell arrays could be passed to a function in a similar manner as structure arrays. There are two cell arrays, varargin and varargout, which have special role in defining variable number of arguments in a function. In the following, we present an example of a function.

 

function [varargout] = statistics(varargin)
  sum = 0;
  n = nargin;
  for i = 1 : n
    sum = sum + varargin{i};
   end;
   mean = sum /n;
   varargout{1} = mean;
   var = 0;
   for i = 1 : n
     var = var + (varargin{i} - mean).^2;
   end;
   var = var / n;
   if nargout > 1
      varargout{2} = var;
   end;
   if nargout > 2
      varargout{3} = sqrt(var);
   end;

end;
 

This function takes a variable number of input arguments, varargin, and returns a variable number of arguments, varargout. The varargin contains the input arguments in a cell array. In this function, line 3 shows how to compute the number of input arguments.

           nargin

Similarly nargout is used to determine the number of output arguments. Line 6, shows how to use cell array index to get the corresponding input argument.

           varargin{i}

The variable number of output arguments are packed into a cell array, varargout. Line 8, 14 and 15 show how to assign the return values to output arguments. Note that before assignment, you need to know if the output argument is really required. This is done by looking at the number of output arguments using nargout.

The following function call shows how to call this function with different number of input and output arguments.

 

>> [mean var] = statistics(1, 2, 3)

mean =

2.0000

var =

0.6667

 

>> [mean var std] = statistics(1, 2, 3, 4, 5)

mean =

3.0000

var =

2.0000

std =

1.4142

 

>> statistics(1, 2, 3, 4, 5)

ans =

3.0000