This sections explains
EULER uses the following data types
The meaning of the first five data types should be clear. EULER tries to keep an evaluation real. But as soon, as complex data is involved the computation gets complex. That is why
>sqrt(-1)
results in a wrong answer, but
>sqrt(complex(-1))
is 0+1*i. complex(x) is a way to make a real number complex.
Strings are used for explaining output, file names, passing functions and expressions to functions, and function key texts. There are only two operators, like the concetanation | and the compare operators.
References are used internally for parameters of functions (see the programming section).
Functions are the user defined functions including the functions in the utility files.
All these data are kept on the stack. Usually, the user does not have to worry about the stack, since EULER uses normal mathematical notation for expressions. Internally, the evaluation of an expression uses the stack rather heavily. Programs are kept in the lower area of the stack. The stack is also used to pass parameters to built-in or user defined functions and to keep the local variables of these functions.
Finally, we remark that the data explained in this section are different from built-in functions which can be used in the same places as user defined functions. There are also commands, which cannot be used in expressions, nor in functions. Built-in functions and commands are part of the code of EULER.
A complete list of built-in functions, commands and user defined functions is printed by
>list
A list of all variables can be obtained with
>listvar
If size information is needed, the command
>memorydump
is available. A hexdump of any data can be obtained with
>hexdump name
but it will only be useful for insiders.
>store("filename")
stores the content of the EULER stack into a file.
>restore("filename")
loads that file. This is a short way of storing a session including the global variables and functions. Note that the file will be system dependend.
Normal EULER input is either a "command", an "expression" or an "assignment". EULER works a bit differently in programming mode, which is indicated by a different prompt.
An example for a command is
>quit
which quits the EULER system. By and by, we will mention a few others. Another example is "load", which you already used to load the demo.
An expression is a valid EULER expression, and has a value as the result. If it is entered on its own or followed by a comma ",", this value is printed.
>3+4*5
prints the value 23.00000. The print is surpressed, if the expression is followed by a semicolon ";". This makes sense, because some functions have side effects and their result is not needed, or because the user does not want to see the long output of an assignment.
The printing is done in a format determined by the function
>format([n,m])
where n is the total width of print and m is the number of digits after the decimal dot. As often,
>format(n,m)
does the same thing, but is a little bit slower since it is a function in UTIL. The output automatically switches to exponential format, if there is not enough space to display the number in fixed format. There is also the command
>goodformat(n,m)
which does ommit decimal digits, if they are zero.
>longformat()
is a function in UTIL, which sets a longer output format, while
>shortformat()
sets a shorter one. Both use goodformat. The longest format is
>longestformat()
You can explicitely specify to have exponential format or fixedformat with
>expformat(n,m) >fixedformat(n,m)
There is also support for output as a fraction (like 1/3).
>fracformat(n,eps)
will output numbers with n places and an accuracy of eps as fractions. Default for n is 20 and, for eps is the internal epsilon. So these paramters can be omitted. The other formats (like shortformat) switch off this type format.
For intervals, you may use
>iformat(n)
This will print as many digits as necessary to show the differences between left and right interval bounds. The output width will be at least n.
>iformat(0)
switches back to the usual format.
An assignment looks like
>variablename=value
The variable name must start with an alphanumeric, and continue with alphanumeric characters or digits. The command assigns the value to the variable, which is declared by the assignment, and prints the value. If the assignment is followed by a ";", then the printing is surpressed. An assignment may be followed by ",", which prints the right hand side of the assignment.
The syntax is of a multiple assignment is
>{x,y,...}=expression
This does make sense only in the cases, when the expression is the result of a function with multiple return values. If a multiple expression is assigned to a single variable, only the first value is used.
The most simple expressions are variables. Their value is the value of the variable, and their type is the type of the variable. If the variable is undefined, interpreting the expressions will stop with an error message.
The basic constant expressions are numbers. Those are entered in the usual form 100, 100.0, 1e2, or 1.0e+2. The letter "small e" indicates powers of 10. An appendix "i" indicates multiples of the complex unit "i". "1+1i" is in fact a sum of 1 and 1i, which is the proper way to enter complex numbers.
A matrix is entered in the brackets "[" and "]" row by row. The columns are seperated by "," and the rows by ";". Not all rows need to be entered in full length. For example
>A=[1,2,3;4,5;6]
is equivalent to
>A=[1,2,3;4,5,0;6,0,0]
The matrix is real, if all entries are real, otherwise it becomes complex. If an entry of a matrix is an interval, the matrix becomes an interval matrix.
If a row is shorter than the others, it is filled with zeros. A matrix constant can spread over several lines.
One can also use a 1xn matrix as part of the row in a matrix, like in
>x=[1,2,3,4] >A=[7,x]
A will be [7,1,2,3,4] then.
String constants are enclosed in double quotes, like in
>string="This is a text"
or in two single quotes to make it possible to include quotes in strings
>string=''This is a "text"''
The section on the line editor shows how to insert a double quote into a string. A single character with ASCII code n can be produced by
>char(n)
A submatrix is a matrix, which is made up by the entries of another matrix. The simplest example is a matrix element
>A[1,1]
which is the element in the first row and column of A.
Let us assume now that A is a matrix and r and c are vectors. Then A[r,c] results in a matrix, which consists of the rows r[1],r[2],... of A, and from these rows, only the columns c[1],c[2],... are taken. Example
>A[[1,2],[1,2]]
is the upper left 2x2 submatrix of A. If a row or column does not exist, it is simply neglected. Thus, if A is a 4x4 matrix, then A[[4,7],[4,7]] results in the value A[4,4]. A special thing is A[i], which is the either the i-th row of A, or if A is a 1xn vector, the i-th element, i.e. A[1,i].
A ":" indicates all rows or columns; i.e., A[:,1] is the first column of A, and A[:,:] is A itself. Another example
>v=[-1,-2,-3,-4,-5]; v[[5,4,3,2,1,1]]
is the vector [-5,-4,-3,-2,-1,-1]. If A is a 4x4 matrix, then A[[2,1]] is a 2x4 matrix, which consists of the second row of A on top of the first row. Note, that there may be a 0xN or Nx0 matrix.
Submatrices can be assigned values. Thus
>A[1,1]=4.5
is a legal statement. However, if the submatrix has more than one element, the value must either be a matrix of equal size or a scalar. I.e.
>A[1:2,:]=0
will set the first two rows of A to 0. If a submatrix gets complex, the matrix gets complex. If v is a 1xN or Nx1 matrix (i.e., a vector), then v[1] is the first element of v; i.e.,
>v=[1.5,-2,0,4.8]; v[3]
is 0.
For compatibility reasons, the square brackets can be replaced by round brackets. Thus, A(1,1) is the same thing as A[1,1]. But A[1,1] is faster. Furthermore, if there is a function A, then A(1,1) will result in a function call to A.
A{i} is the i-th element of the matrix A, as if the NxM Matrix A was a vector of length N*M. This is useful for making functions work for matrices, and is really the quickest way to access a matrix element. It works also, if the matrix A is to small or a real or complex scalar variable. Then the result is the last element of A.
The ":" serves to generate a vector quickly. Thus
>1:10
generates the vector [1,2,3,4,5,6,7,8,9,10]. A step size may be given as in the example
>5:-1.5:1
which yields [5,3.5,2]. By numerical reasons, one cannot expect to hit 1 exactly with 00.11. However, the program uses the internal epsilon to stop generating the vector, so that 00.11 yields the desired result. By default, the internal epsilon is set so that even
>0:0.0001:1
works correctly.
If A is a matrix expression (an expression of type matrix), then A' is the transposed matrix.
The binary operator "|" puts a matrix aside another; i.e., if A is a NxM matrix and B is a NxK matrix, then A|B is a Nx(M+K) matrix, which consists of A left of B. Analogously, A_B puts A atop of B. These operators work also for numbers, which are treated as 1x1 matrices. They do even work, if A is a Nx0 or 0xN matrix.
The mathematical operators +,-,*,/ work as usual for numbers. For matrices they work elementwise. However, the matrices need not necessarily have the same size. There are some special rules.
Of course, the same rules hold for all other operands and functions of two parameters. The reason for these rules will become apparant later on. But the guidline is, that one can easily generate tables of functions for tables of parameters. Just one examples is the table
>(1:10)*(1:10)'
which contains all products i*j.
Of course, -A negates all elements of A. EULER knows the rule, to compute "*" and "/" before "+" and "-". One can also write ".*","./" for compatibility reasons. If A has a different size as B, and neither A or B is a 1x1 matrix or a number, then A+B results in error.
Note, that the matrix product is computed with "A.B".
Of course, one can use the round brackets ( and ) to group expressions like in
>(1+5)*(6+7^(1+3))
The power operator can be written "^" or "**" (or ".^"). It computes the power elementwise, like all the other operators. So
>[1,2,3]^2
yields [1,4,9]. The power may also be negative; i.e., the integer powers of all numbers are defined. For a matrix, inv(A) computes the inverse of A (not "A^-1"!). Note, that "^" has precedence, so
>-2^2
is -4.
Comparison of values can be done with > ,> =,< ,< =, != (not equal) or == (equal). They result in 1 or 0, where 1 is TRUE. Again, these operators work elementwise; i.e,
>[1,2,3,4]>2
yields [0,0,1,1].
>!A
(not A) is a matrix, which is 1 on all zero elements of A, and 0 on all nonzero elements of A.
>A && B
is a matrix, which is 1 whenever the corresponding elements of A and B are nonzero.
>A || B
is 1 whenever the corresponding element of A is nonzero or the corresponding element of B is nonzero.
>any(A)
yields 1 if any element of A is nonzero.
One can change dimensions of a matrix with
>B=redim(A,[n,m])
or
>B=redim(A,n,m)
This will copy the content of A to B filling with 0 if necessary. A matrix is stored row by row.
There are several built-in functions which generate matrices. The most elementary ones are zeros([N,M]) and ones([N,M]), which can also be written zeros(N,M) and ones(N,M). They produce a NxM matrix, which is filled with ones or zeros respectively. Note, that one can also generate 0xN and Nx0 matrices. So
>zeros[0,5]_v_v
is a legal statement, if v is a 1x5 vector.
>size(A)
returns the size of the matrix A as a 1x2 vector [n,m]. It is also possible to give size several arguments. Then
>size(A,B,...)
results in the size of the largest matrix of A,B,... However, all matrixes in the list must have the same size, unless their size is 1x1. The use of this feature will become apparent later on. Also
>cols(A) >rows(A)
return the number of columns and rows of a matrix A.
>length(A)
it the maximum of the number of columns and rows. More generally,
>matrix([N,M],x)
or matrix(N,M,x) returns a NxM matrix filled with x, which may be real or complex.
>diag([N,M],K,v)
produces a NxM matrix, which has the vector v on its K-th diagonal and is 0 everywhere else. If v is not long enough, the last element of v is taken for the rest of the diagonal. The 0-th diagonal is the main diagonal, the 1-st the one above, and the -1-st the one below. So
>diag([5,5],0,1)
produces the 5x5 identity matrix. The same can be achieved with the utility function
>id(5)
One can also write diag(N,M,K,v).
>diag(A,K)
is a vector, which is the K-th diagonal of A.
>dup(v,N)
duplicates the 1xM vector N times, such that a NxM matrix is generated, which has v in each row. If v is an Mx1 vector, then v is duplicated into the N columns of a MxN matrix. dup works also, if v is a number. Then it generates a column vector.
>B=band(A,N,M)
sets all elements of A[i,j] to 0, unless N< = i-j< = M.
>B=setdiag(A,N,v)
sets the N-th diagonal of A to v. v may be a number or a vector.
>bandmult(A,B)
multiplies to matrices A and B (like A.B), but is considerably faster, if A and B contain lots of zeros.
>symmult(A,B)
multiplies symmetric matrices A and B and saves half of the time.
There are four practical functions shiftleft, shiftright, rotleft, rotright, which shift and rotate the columns of a matrix left or right. E.g.,
>shiftleft(1:4)
will produce the vector (2,3,4,0) and
>rotleft(1:4)
the vector (2,3,4,1).
Furthermore,
>flipx(A)
flips the matrix, such that the last column becomes the first, the first column the last.
>flipy(A)
does the same to the rows.