# Octave and Matlab oddities

*Update 2019: Matlab has since fixed this behaviour, so it now matches Octave.*

This page contains my notes on quirks in the Matlab and Octave programming languages, especially where they differ. Historical note: Octave started out as its own language with many similarities with Matlab. These days Octave strives to support a superset of Matlab’s syntax.

## Environment capture by anonymous functions

Create a file called `func_creator.m` like
this:

function [fn, fn2] = func_creator() A = [3 1 4 1 5 9]; fn = @(x) eval(x); fn2 = @() A; A = 'doom';

Now guess the output of running `fn_demo.m`:

[fn, fn2] = func_creator(); fn2() fn('A')

The behavior of `fn2()` is as expected from the documentation: in
Octave and Matlab it captures the value of `A = [3 1 4 1 5 9]` at the
time it was created. In Octave `fn('A')` gives an error as I expected,
but Matlab returns `'doom'`. When an anonymous function is created,
Matlab actually stores a copy of the whole environment(!). More accurately,
Matlab no longer clears the environment from memory when it would normally go
out of scope. The anonymous function doesn’t see a snapshot of the
environment at the time the function was created, but its current state.

Matlab’s behavior is a pain, as memory usage occasionally balloons when working with anonymous functions. I sometimes have to create little helper functions that create my functions in a clean environment in order to avoid leaving more variables stored in memory than I intended.

For comparison, Python does not waste memory in the way that Matlab does:
variables that are not explicitly referenced by a nested function are cleared.
As with Octave, `eval`-based tricks that attempt to reference them fail.
A potential source of confusion is that Python never “snapshots” the
variables like Matlab/Octave does. Indeed Python nested functions can reference
variables in the surrounding scope before they are even created.

## Minimal evaluation or Short-circuit evaluation

*Update 2019: Octave now matches Matlab's behaviour for the first example
below, but emits a warning about it.*

In Octave, as in C, the `||` operator
short-circuits.
The `|` does not, although it has different meanings in Octave and C.
Matlab has the same behavior, except in `if` statements where if every
element of the first argument to `|` is non-zero then a short-circuit
occurs. Similarly for & and &&. I prefer Octave’s behavior,
where operators behave in the same way wherever they appear. However, if
Mathworks were to “fix” Matlab, then some existing code would be
broken. I’d stick to `||` in `if` statements unless you are
sure you know what you are doing.

Example: the following two lines of code are equivalent in Octave but not in Matlab:

if (1 | figure); x=3; end y=(1 | figure); if y; x=3; end

Both lines pop up a figure window in Octave (if one was not already open), the first line does not in Matlab.

The Matlab documentation says: “Using the element-wise operators (& and |) for short-circuiting may yield unexpected results.” Indeed!

## Arrays with some of the sizes equal to one

What a nightmare. The languages are too “clever” for their own good.

In both languages `sum(A)` sums over the first non-singleton
dimension. Too much code assumes it means exactly the same as `sum(A,1)`.
This will cause problems if occasionally A has only one row. It’s best to always
put in the index you want summed. This advice applies to many other Matlab
functions. For example say `max(A,[],1)` rather than `max(A)`.

Multiple dimensional arrays cause more problems; in general it seems
impossible to create an array with trailing singleton dimensions. Example:
`size(repmat(1,[a,b,c]))` returns `[a,b,c]`, unless `c==1`,
in which case it returns `[a,b]`. GAAHHH! Presumably this is meant to be
for convenience...to reduce the number of calls to `squeeze`. The
downside is that Matlab is *full* of kludges to work around problems
caused by this issue. Examples: if you ask for element `A(1,1,1)` then it
returns a value even if `A` does not have a third dimension; permute can
access singleton dimensions that don’t exist. In the past Octave has had
compatibility problems, but now matches much more of Matlab’s behaviour.
However, in either language not *all* functions you use necessarily let
you give them matrices if they expect larger arrays. Until very recently
`sort(randn(3,2,1), 3)` was broken in Matlab (fixed in v7.7) and
Octave (fixed in a v3.3 dev version). This means that robust code is hard to
write and can be complicated, because sometimes you have to check for singleton
dimensions to avoid crashes, and it isn't always obvious when this is
necessary.

## Passing by reference

There are no references in the Matlab language, although the situation isn’t as bad as some people think. If you pass a large matrix to a function and only read that matrix within the function then Matlab doesn’t actually copy the memory. It automatically “passes by reference”. Freemat adds new syntax for pass-by-reference to its clone of the Matlab language, but benchmarking my copy, it appears to still temporarily copy the memory if you alter the matrix!

One reason for wanting a true pass-by-reference is for efficient in-place operations (like an in-place quick-sort or Cholesky-decomposition). However, I don’t necessarily agree with adding to the language (as in FreeMat). It seems to me that if a function is called like this:

C = chol(C);

And the function is defined like this:

function A = chol(A)

Then the interpreter could automatically do stuff in place. Admittedly things
could be a bit more complicated if slices of arrays are used for inputs and
outputs. A language feature could be added to the languages’ mex/C
interfaces allowing external code to ask if it’s allowed to alter things
in place. eg if `mymex` were called with `C=mymex(C);` then the
`mymex` function could be told it is allowed to alter `C` in
place.

I did some experiments with FreeMat 1.10, Octave 2.1.69 and Matlab 7.0.1 to confirm how much memory is used when passing matrices around under various circumstances. None of them did operations in place when they could have done.

**Update:** there has been some
progress on this issue in Matlab. The optimization described above has
now been implemented, as long as the function is called from within a function
(not a script or from the command-line). Sadly there still isn’t a
documented, safe way of changing variables in place in mex files (there are
dodgy unsupported ways of doing it, but that is asking for trouble).

A real example of the benefits of in place operations is plus_diag.m (see tricks page), which adds something onto the diagonal of an existing matrix. A horrible hack used to dramatically out-perfrom this function, but doesn’t any more in recent Matlab (unless being called from a script or the command-line).

## Sparse Matrix oddity

*This documents an oddity in old versions of Matlab. It was definitely
fixed by v7.4,
but I’m not sure when it was first fixed. I seem to remember that
Octave got it right, then copied Matlab’s buggy behaviour and then
went back to being correct again.*

`0^0 == 1` right? Unless the zero is in a sparse matrix in (some
versions of) Matlab:

>> A = sparse([0,1]) A = (1,2) 1 >> A.^0 ans = (1,2) 1

Similarly in some versions of Matlab dividing by zero doesnâ€™t turn zeros into NaNs. Now both Matlab and Octave act correctly on the zero-elements, treating them as zeros. To operate on just the non-zero elements we can do:

>> spfun(@(x) x^0, A) ans = (1,2) 1