Yorick, One of the Fastest Matrix Language Options Available
|
The plot at the left is the Yorick math language version of a mesh. It is a
graph of the sinx/x function, which is also the 3D graphic of a star image as
seen through a telescope. In this image you can see some interesting shading
not seen in all math language mesh graphics. Yorick's mesh routines allow
adjustments to be make in shading, light direction, and other viewing
options.
|
Yorick Syntax
Yorick is a scripting
matrix language created by a physicist for doing general prototyping in
scientific work, data processing, and simulation. The language is described as
being like Basic or Lisp, but far faster.
Yorick uses a C like syntax, so programmers of C, Java, and perl will find
themselves at home with Yorick. Even the looping commands in Yorick are C like.
If, however, you are currently a MATLAB or MATLAB clone user, you'll encounter
a bit of adjustment in moving to Yorick.
User function files in Yorick must be pre-loaded before being used, unlike
MATLAB and Octave in which functions are auto-loaded on reference. Putting
related functions in libraries seems to be the most efficient way of packaging
user-defined functions. User created Yorick files end with extension i,
and the file custom.i allows users to list modules they want loaded each
time Yorick is invoked.
|
Yorick is available in Windows and Linux. In windows, the language presents
a moderate GUI interface. This review only deals with the Linux version of
Yorick. In Linux, the user interface is a very basic command line interface. In
fact, the basic interface doesn't even have a history mechanism, and is
thus very difficult to work with.
|
|
But -- Don't Lose Faith.
The Linux interface for Yorick can be dramatically improved in two ways. The
Yorick documentation shows how to implement Yorick in conjunction with the
popular emacs editor, with emacs becoming the interface to Yorick. A
simpler mechanism is to use a utility named rlwrap. Rlrwap provides a
front end for virtually any program, providing a command history as well as
additional optional features. The syntax of rlwrap is simple:
rlwrap -c yorick
That simple rlwrap command starts Yorick and becomes an interface to Yorick
that provides the command history and other features (like file name
completion) to Yorick. Replacing the word Yorick in the rlwrap command with
some other program will create a front end for that program.
Yorick's syntax, once learned, is very convenient for interactive work. Most
languages provide some kind of function for passing commands to the operating
system. Something like system("ls *.i") to tell the system to do a
listing of all .i files. Yorick provides such a function, but provides a
much handier way to pass commands to the system when working interactively,
making the operating system commands seem much more like part of an integrated
environment. To pass a command to the operating system Yorick-style, just
precede the command with a dollar sign. For example:
$ls *.i
Tells the operating system to list all .i files.
In Yorick, math operators are assumed to be applied in scalar fashion,
unlike the matrix assumption in MATLAB and Octave. In the following matrix
equations, the first equation does a scalar cell upon cell multiplication of
matrices x and y to get z. The second equation performs a
full matrix multiplication of x and y to get z.
Scalar product of matrices: z = x * y;
Matrix product of matrices: z = x(, +) * y(+ ,);
The odd looking nature of the matrix multiply in the second equation is due
to the fact that Yorick isn't limited to two-dimensional matrices. Matrices may
be of virtually any number of dimensions. Because of the multi-dimensional
nature of Yorick, matrix math operations must be able to provide information
about the nature of the operation and dimensions involved.
Yorick allows users to create variables of many types, not just double
precision matrices. One can create short, int, float (single precision), and
double arrays and matrices. While this gives the user better control of memory
usage, it can cause confusing math results. An int array divided by an integer
scaler will not yield any fractional results, for example. The user must keep
track of the types of variables used in equations to be sure the results are as
expected.
Variables passed to functions in Yorick are operated on as local
variables within the functions. That is, modifications to a passed variables
value are lost when the function returns. Only the values explicitly
returned by a return statement get passed to the calling routine.
This local behavior methodology can be affected in a few ways. If an
array is passed to a yorick function, operating on an element of the array
will affect the calling functions respective array element, as follows:
x = [10,11,12];
somefunction(x);
func somefunction(x){
x(2) = x(2) * 2; // results in x(2) being changed in calling function
}
Another method to allow a function to change the value of a variable beyond
the local version is to use the & symbol on front of a variable name
in the function definition, as follows:
somefunction(&x){
x *= 2; // results in x being changed in calling function
}
Notice the *= operator in the previous example. The shortcut
c style math operators are recognized by yorick.
Finally, values can be declared non-local with an extern statement in
a function declaration, as follows:
x = 10;
y = 20;
somefunction(y);
func somefunction(y){
extern x;
x *= 2; // causes x to be changed in calling routine via extern
y *= 2; // changes to y are local since not listed in extern
}
Yorick has a healthy population of mathematical functions, from statistical
to signal processing -- plus a number of routines used in modeling
calculations. Matrix indexing has some interesting shortcuts not available in
all matrix languages. Indexes run from 1 to n, but a user can reference the
last element of an array (or any dimension of a multi-dimensional matrix) with
the index zero. Thus x(0) refers to the last element of the array x.
x(-1) refers to the next to last element of the array, etc.
One thing I like most about Yorick is that it is fast! Really fast.
All of the matrix languages perform matrix operations fast, but most matrix
languages really bog down in instances when the user is forced to resort to
loops to complete an operation. Yorick, however, can even process through loop
procedures very quickly. The Yorick documentation gives some good guidelines
for when a user can expect to be able to vectorize a solution and avoid
loops.
Functions in Yorick can only return a single entity. Normally that's a
scalar or a matrix of some number of dimensions. It is possible to declare
variables within functions as external, making multiple variables in a function
available to other functions.
It is also possible to declare a C like struct to hold variables. While
structs cannot be declared in functions, they can, after having been declared
in the main routine, be used in functions. This gives an additional way for
functions to pass back multiple values -- by placing them into a struct.
Yorick programs can easily be ran in a batch mode. There are actually two
ways to do this. In one way, interactive input from the user is not possible,
and the custom.i isn't automatically read on invocation. The other way
leaves user interaction in place, and custom loads are automatically done. Both
methods use a specific command on the first line of a batch file as
follows:
For no run time interaction:
#!/user/bin/yorick -batch
...
For run time interaction:
#!/usr/bin/yorick -i
...
For help, the Linux Yorick install includes a Yorick info file.
Typing info yorick from the Linux shell will bring up the Yorick info
file. Within the language, the user can type help,topic to bring up
help on a given function or topic. Yorick makes documentation of user-defined
functions easy, as the documentation for each function is simply a particularly
structured comment within the respective functions.
Yorick Graphics
Yorick has a sizable collection of graphic primitives which can, with
supplied parameters, create an impressive array of 2D and 3D graphic
presentations. It does take a bit of study to get the hang of some of the
routines, but the output results are worth the effort. Yorick uses a well
integrated implementation of the Gist plot package. It's pretty easy to
repackage Yorick plot commands into commands you're more familiar with,
once you learn about them.
With the Yorick graphics, one can make line graphs, contour graphs, 3D mesh
graphs, and display color images. The graph at the upper left is a color
contour graph made with Yorick.
The graph you see at the upper right is a Yorick color map presentation.
Yorick can present matrix images of large size quickly, and allows the user to
select and easily create different color schemes. One can display images with
either the color option of the contour utility (plc), as shown here, or with
an image display utility (pli). The contour version works best with a limited
number of color levels, less than 20 or so.
Even a simple quick line plot in Yorick produces an active plot window. As
one moves the mouse around within the plot, the engineering coordinates of the
mouse position are instantaneously displayed at the top of the plot. Clicking
on the plot causes an instant redisplay of a zoomed in plot. Clicking on the
right mouse button zooms out. One can zoom the entire plot, or just the x or y
axis.
Mouse location and button information can be obtained by a Yorick program.
This feature, combined with the fast plotting speed of graphics, makes Yorick
one of the more capable matrix languages for image processing. Included with
the Yorick install is a comprehensive set of fits image file utilities.
This allows the user to input, manipulate, and output fits format files. Yorick
also has read and write routines for ppm, pgm, and pbm file formats.
Combined with the convert utility of the imagemagick package puts
images of all types within the reach of Yorick.
The image at the upper left is an example if using the image graphic
command instead of the contour command. With it, one can get the full
256 colors of a color map to be shown instead of the digitized look of
a small number of colors.
The image at the upper right is a 3D mesh with hidden lines. As you
can see, the highlights possible with the 3D command (plwf) give a very
easily interpreted 3D display.
|
Yorick can even make and present movies, like the movie of the rippling
sinx/x curve that you see here. Yorick has an animate command that can
repeatedly call a computational function and present the results at a user
designated rate.
|
Summary
In summary, I find Yorick to be an easy to use matrix language for a wide
range of computational solutions. It is well supplied with mathematics routines
for filtering, Fourier analysis, signal processing, and regression. It has
robust enough I/O support to allow a user to tailor routines to read most any
ASCII or binary file whose format is known. It has some unique graphics
methods, and provides possibilities for the solution of some very complex
problems with it's multi-dimensional capabilities.
I have used it extensively both for modeling problems and for time
series reduction and analysis. I found that with the speed of Yorick, I
seldom had to resort to writing a compiled program in some other language.
My subjective pros and cons list for Yorick follows.
Pros:
Yorick is freely available for both Linux and Windows.
Yorick is very fast. Even when one resorts to loops,
Yorick remains respectably fast.
Yorick closely follows C programming syntax. So users familiar with
C, Perl, or Java will learn it quickly.
Yorick supports highly interactive 2D and 3D plots. By default one
can expand or contract any graph in X, Y, or both coordinates.
Mouse clicks on graphs can deliver information back to a Yorick script.
Yorick has sufficient low-level file I/O routines to allow it to read or
create files compatible with external utilities.
Yorick supports fits and pnm graphic files.
Yorick has sufficient string handling functions to deal with parameters
and straight forward ASCII data.
Yorick can support a C-style data structure to allow returning more than
one argument from a function.
Yorick supports char, integer, double, and complex data types.
Yorick supports arrays, and multi-dimensional arrays, at least as high
as 9 dimensions.
Yorick has a very effective debugger that lets you examine variable
values within a crashed function.
Yorick works well in both interactive and batch modes.
Cons:
While Yorick has some string handling capability, it's limited in
support of more complex ASCII files.
Yorick has a very simplistic user interface. You'll want to either use
rlwrap or emacs as an interface for Yorick.
Some of the matrix operators are a bit arcane, adding to the
learning curve.
All functions must be in library files, and only those listed in the
custom.i file are automatically loaded.
Data structure layouts must be globally declared.
|