Differences between Octave and MATLAB

Octave has been mainly built with MATLAB compatibility in mind. It essentially shares a lot of features in common with MATLAB

  1. Matrices as fundamental data type.
  2. Built-in support for complex numbers.
  3. Powerful built-in math functions and extensive function libraries.
  4. Extensibility in the form of user-defined functions.

Some of the differences that do exist between Octave and MATLAB can be worked around using “user preference variables.”

GNU Octave is mostly compatible with Matlab. However, Octave’s parser allows some (often very useful) syntax that Matlab’s does not, so programs written for Octave might not run in Matlab. For example, Octave supports the use of both single and double quotes. Matlab only supports single quotes, which means parsing errors will occur if you try to use double quotes (e.g. in an Octave script when run on Matlab). Octave and Matlab users who must collaborate with each other need to take note of these issues and program accordingly.

Note

Octave can be run in “traditional mode” (by including the —traditional flag when starting Octave) which makes it behave in a slightly more Matlab-compatible way.

This chapter documents instances where Matlab’s parser will fail to run code that will run in Octave, and instances where Octave’s parser will fail to run code that will run in Matlab. This page also contains notes on differences between things that are different between Octave (in traditional mode) and Matlab.

Tip for sharing .mat files between Octave and Matlab: always use save -V6 if you are using Matlab 7.X. Octave version 2.1.x cannot read Matlab 7.X .mat files. Octave 2.9.x can read Matlab 7.X .mat files.

load

For compatiblility, it is best to specify absolute paths of files for LOAD. Matlab (7.0) vs Octave (2.1.71): paths are not searched for .mat files in the same way as .m files

Matlab:

a = 1; save /tmp/a.mat a ; addpath('/tmp'); load a.mat
% OK

Octave:

a = 1; save /tmp/a.mat a ;
LOADPATH=['/tmp:',LOADPATH];
load a.mat
% error: load: nonexistent file: `a.mat'

For any other purpose, don’t use absolute paths. It is bad programming style. Don’t do it. It causes many problems.

C-Style Autoincrement and Assignment operators

Octave (3.0.1) supports C-style autoincrement and assignment operators:

i++; ++i; i+=1; etc.

MatLab (7.0) does not.

product of booleans

Matlab (7.0) and Octave (3.0.2) responds differently when computing the product of boolean values:

X = ones(2,2) ; prod(size(X)==1)

Matlab: ??? Function 'prod' is not defined for values of class 'logical'.
Octave: ans = 0

nargin

Matlab (7.0) will not allow the following; Octave (2.1.71) will.:

function a = testfun(c)
 if (nargin == 1)
  nargin = 2;
 end

startup.m

Matlab will execute a file named startup.m in the directory it was called from on the command line. Octave does not. It will, however, execute a file named .octaverc.

[‘abc ‘;’abc’]

[‘abc ‘;’abc’] is allowed in Octave; Matlab returns: ?? Error using ==> vertcat

In Octave the result will be a 2 by 4 matrix where the last element of the last row is a space.

Calling Shells

the ”! STRING” syntax calls a shell with command STRING in Matlab. Octave does not recognize !. Always use system(STRING) for compatibility.

If you really miss the one-character shortcut, for convenience on the command line you can create a similar shortcut by defining the following in your 2.9.x octave startup file:

function S(a), system(a); end
mark_as_rawcommand('S')

Now “S STRING” will evaluate the string in the shell.

hist

hist.m in Octave has a normalization input, Matlab does not.

Getting Version Information

Octave (2.1.7X) uses “OCTAVE_VERSION”, Matlab uses “ver” for version informaton. (Octave 2.9.5 and later has “ver”, so is compatible in this sense.)

Format of printing to screen

Cell arrays and structures print to screen in different format. There may be switches to make them the same, for example, struct_levels_to_print. None are set in –traditional mode, however.

Attempting to load empty files

MATLAB lets you load empty files, OCTAVE does not:

system('touch emptyfile') ; A = load('emptyfile')
Matlab 6.5    : A=[]
Octave 2.1.71 : error: load: file `emptyfile' seems to be empty!
                error: load: unable to extract matrix size from file `emptyfile'

fprintf and printf

Matlab doesn’t support ‘printf’ as a command for printing to the screen:

foo = 5;
printf('My result is: %d\n', foo)

works in Octave, but not Matlab. If using Matlab, ‘fprintf’ covers writing both to the screen and to a file:

foo = 5;
fprintf('My result is: %d\n', foo)

In Matlab, the omission of the optional file-handle argument to fprintf (or using the special value 1 for standard output or 2 for standard error) causes the text to be printed to the screen rather than to a file.

Whitespace

Matlab doesn’t allow whitespace before the transpose operator:

[0 1]'

works in Matlab, but:

[0 1] '

doesn’t. Octave allows both cases.

Line continuation

Matlab always requires ‘...’ for line continuation:

rand (1, ...
      2)

while both:

rand (1,
      2)

and:

rand (1, \
      2)

work in Octave, in addition to ‘...’.

Logical operators (And, Or, Not)

Octave allows users to use two different group of logical operators: the ones used in Matlab, or the ones familiar to C/Java/etc programmers. If you use the latter, however, you’ll be writing code that Matlab will not accept, so try to use the Matlab-compatible ones:

  • For not-equal comparison, Octave can use ‘~=’ or ‘!=’. Matlab requires ‘’’ ‘~=’ ‘’‘.
  • For a logical-and, Octave can use ‘&’ or ‘&&’; Matlab requires ‘’’ ‘&’ ‘’‘. (note: Matlab supports ‘&&’ and ‘||’ as short-circuit logical operators since version 6.5.)
  • For a logical-or, Octave can use ‘|’ or ‘||’; Matlab requires ‘’’ ‘|’ ‘’‘. (note: Octave’s ‘||’ and ‘&&’ return a scalar, ‘|’ and ‘&’ return matrices)

Octave Controls System Toolbox

Both MATLAB and Octave have toolboxes intended to control system design. In Octave, the toolbox is called the Octave Controls System Toolbox. Users of Debian and its derivatives can install it by installing the package “octave-control”, if it is not installed by default.

In Octave, initialization of a ‘’system data structure’’ (simply, a system model) works very much as in MATLAB: one can use tf, ss or zp commands in order to initialize a system data structure in form of a transfer function, state space model or zero-pole representation. However, while in MATLAB one may write simply F = G + H to sum up two systems or F = G*H to connect two systems in series, in Octave for that purpose one have to use sysadd/syssub and sysmult, respectively.

For more information about functions’ syntax, type help <name of function>. For more information about the Controls System Toolbox, start the Octave Controls System Toolbox Demo demo/tutorial program by typing DEMOcontrol in Octave command prompt.

Example code in MATLAB:

F = G + H

Code in Octave doing the same:

F = sysadd(G, H)

Both approaches seems to work analogous, though MATLAB’s looks a bit more clear. Hopefully, that would be fixed in future versions of Octave, since one of its primary goals is to wholly support the syntax of MATLAB. But there is no guarantee, and even no note about any attempt has yet been published.

Extending Octave with Fast, Compiled Languages

Developers may want to extend Octave by adding C, C++, or Fortran programs to the built-in functions of Octave. This may be done because the compiled programs will be faster to execute than Octave or to add existing C, C++, or Fortran code to Octave.:

mkoctfile [-options] file

The mkoctfile function compiles source code written in C, C++, or Fortran. Depending on the options used with mkoctfile, the compiled code can be called within Octave or can be used as a stand-alone application. mkoctfile can be called from the shell prompt or from the Octave prompt.

Octave is written in C++, so the approach taken here is to write C++ functions which call Fortran functions or subroutines, and then set up the C++ functions as ‘dynamically linked’ functions for Octave. These can then be called from the Octave command line or in Octave functions just like any other Octave function.

First, a very simple example to get started. It won’t be “hello, world”, because strings are a bit tricky. Instead, say we have the Fortran subroutine

SUBROUTINE NINE (R)
DOUBLE PRECISION R
R = 9D0
END SUBROUTINE NINE

we’d write the C++ wrapper

#include <octave/oct.h>
#include "f77-fcn.h"
extern "C"
{
  int F77_FUNC (nine, NINE) (double& R);
}
DEFUN_DLD (o9, args, ,
         "- Loadable Function: [NINE] = o9 ()\n\
     \n\
     Returns the number nine.")
{
  octave_value_list retval;
  double r;
  F77_XFCN (nine, NINE, (r));
  if (f77_exception_encountered)
    {
      error ("unrecoverable error in o9");
      return retval;
    }
  retval(0) = octave_value (r);
  return retval;
}

compile them (at the shell, not in Octave, the “$” being the shell’s prompt) with

$ mkoctfile o9.cc nine.f

assuming those are the names of the files containing the C++ wrapper and the Fortran subroutine. Then o9 is available in Octave like any other function

octave:1> o9
ans = 9

Fortran has different calling conventions from C/C++, and conventions vary from system to system, and perhaps between compilers on the same system. A set of macros hides the details.

  • Fortran is not case-sensitive but the linker is, so the compiler changes the name of the function to all uppercase or all lowercase. The F77_FUNC(name,NAME) macro selects the appropriate name given upper and lower case versions of the name. Use it instead of the name when declaring or calling the function.

  • If you don’t trust your fortran routine with all inputs you should call it with

    F77_XFCN (name, NAME, (args...));
    
  • If you are sure it will not generate any signals or run for excessive time, you can use

    F77_FUNC(name,NAME)(args...);
    
  • Use of underscores in the Fortran subroutine name causes some problems. Some compilers add trailing underscores, some add none, some only add an underscore if there is not one there already. If your function name contains a trailing underscore, you need to use F77_FUNC_(name,NAME).

  • Fortran subroutines may or may not return a value (functions always do of course). Use F77_RET_T as the return type for a Fortran subroutine in the declaration.

  • In Fortran, all parameters are pass-by-reference, which means that you need to declare type& for scalar parameters and type* for vector parameters.

  • Fortran strings have an intrinsic length, and unlike C, do not use a trailing 0 to determine the length of the string. When you pass a string or a string constant to a subroutine, you have to also pass the length. Some compilers treat strings as structures (so length and data are passed together) and others pass the length of the strings after every other parameter has been passed.

  • Rather than using “char*” for string argument declarations and one extra “int” declaration at the end for each string length, you need either

    F77_CHAR_ARG_DECL
    
  • or the following, depending on the const-ness of the argument

    F77_CONST_CHAR_ARG_DECL
    
  • At the end of the argument list, leave the option for a string length declaration if that’s what the compiler uses

    F77_CHAR_ARG_LEN_DECL
    
  • To call a function with a string argument, you need to use one of the following in place of the string argument

    F77_CHAR_ARG(x) for non-const arg, len = strlen(x)
    F77_CONST_CHAR_ARG(x) for const arg, len = strlen(x)
    F77_CXX_STRING_ARG(x) for const arg, len = x.lenth()
    F77_CHAR_ARG2(x,n) for non-const arg, len = n
    F77_CONST_CHAR_ARG2(x,n) for const arg, len = n
    
  • You need to use the following macro at the end of the argument list for each string you pass. It may or may not be ignored.

    F77_CHAR_ARG_LEN(n)
    
  • There is also a macro F77_RETURN(retval) which is for callbacks to fortran functions.

Fortran Examples

Say we had a Fortran subroutine TNINE

      SUBROUTINE TNINE (IOPT, PARMOD, PS, X, Y, Z, BX, BY, BZ)
      INTEGER IOPT
      DOUBLE PRECISION PARMOD(10), PS, X, Y, Z, BX, BY, BZ
C     This is just a test subroutine body, to check connexions.
C     Put the sum of PARMOD in PS, and X, Y, Z into BX, BY, BZ
      INTEGER I
      PS = 0D0
      DO 1 I=1, 10
         PS = PS + PARMOD (I)
 1    CONTINUE
      BX = X
      BY = Y
      BZ = Z
      END

A minimal C++ wrapper would look like

#include <octave/oct.h>
#include "f77-fcn.h"
extern "C"
 {
   int F77_FUNC (tnine, TNINE) (const int& IOPT, const double* PARMOD,
                                double& PS,
                                const double& X, const double& Y,
                                const double &Z,
                                double& BX, double& BY, double& BZ );
 }
 DEFUN_DLD (t96, args, ,
           "- Loadable Function: [PS, BX, BY, BZ] = t96 (PM, X, Y, Z)\n\
 \n\
 Returns the sum of PM in PS and X, Y, and Z in BX, BY, and BZ.")
 {
   octave_value_list retval;
   const int dummy_integer = 0;
   Matrix pm;
   const double x = args(1).double_value(), y = args(2).double_value(),
   z = args(3).double_value();
   double ps, bx, by, bz;
   pm = args(0).matrix_value ();
   F77_XFCN (tnine, TNINE,
            (dummy_integer, pm.fortran_vec(), ps, x, y, z, bx, by, bz) );
   if (f77_exception_encountered)
     {
       error ("unrecoverable error in t96");
       return retval;
     }
   retval(0) = octave_value (ps);
   retval(1) = octave_value (bx);
   retval(2) = octave_value (by);
   retval(3) = octave_value (bz);
   return retval;
 }

Compile this (in the BASH shell) with

$ mkoctfile t96.cc tnine.f

and run it in Octave like

octave> [p, x, y, z] = t96 (1:10, sqrt (2), pi, e)
p = 55
x = 1.4142
y = 3.1416
z = 2.7183

Some other differences

  • There used to be a difference in datestr between Octave-forge and Matlab. Has this been changed?

  • MATLAB uses the percent sign to begin a comment. Octave uses both the pound sign and the percent sign interchangeably.

  • MATLAB has no fputs function. Call fprintf instead.

  • Octave has no textscan function. Use fscanf instead.

  • load in Matlab = load –force in Octave (should –force be default in –traditional?)

  • page_output_immediately = 1 should this be default in –traditional?

  • For exponentiation, Octave can use ‘^’ or ‘**’; Matlab requires ‘^’.

  • For string delimiters, Octave can use ‘ or ”; Matlab requires ‘.

  • For ends, Octave can use ‘end{if,for, ...}’; Matlab requires ‘end’.

  • Octave supports C-style hexadecimal notation (e.g. “0xF0”); Matlab requires the ‘’hex2dec’’ function (e.g. “hex2dec(‘F0’)”).

  • For “dbstep in” use “dbstep”; for “dbstep” use “dbnext”

  • For “eig(A,B)” use “qz(A,B)”

  • For gallery, compan, and hadamard install http://www.ma.man.ac.uk/~higham/testmat.html

  • For datetick use gnuplot commands:

    __gnuplot_set xdata time
    __gnuplot_set timefmt "%d/%m"
    __gnuplot_set format x "%b %d"
    
  • If something (like Netlab) need a function called fcnchk you can just put the following into a file called fcnchk.m and put it somewhere Octave can find it:

    function f=fcnchk(x, n)
      f = x;
    end
    
  • The Octave plotting functions are mostly compatible with the ones from Matlab 3.x, but not from Matlab 4.x.

  • Matlab includes a “Just-In-Time” compiler. This compiler allows the acceleration of for-loops in Matlab to almost native performance with certain restrictions. The JIT must know the return type of all functions called in the loops and so you can’t include user functions in the loop of JIT optimized loops. Octave doesn’t have a JIT and so to some might seem slower than Matlab. For this reason you must vectorize your code as much as possible and/or extend Octave functions by using fast, compiled languages (C, C++, Fortran)

  • A large number of the Matlab core functions (ie those that are in the core and not a toolbox) are implemented, and certainly all of the commonly used ones. There are a few functions that aren’t implemented, for example condest or to do with specific missing Octave functionality (gui, dll, java, activex, dde, web, and serial functions). Some of the core functions have limitations that aren’t in the Matlab version. For example the sprandn function can not force a particular condition number for the matrix like Matlab can.

  • Octave is a community project and so the toolboxes that exist are donated by those interested in them through the Octave Forge website (http://octave.sourceforge.net). These might be lacking in certain functionality relative to the Matlab toolboxes, and might not exactly duplicate the matlab functionality or interface.

Porting programs from Matlab to Octave

“I wrote some code for Matlab, and I want to get it running under Octave. Is there anything I should watch out for?”

The differences between Octave and Matlab typically fall into one of three categories:

  • Irrelevant.
  • Known differences, perhaps configurable with a user preference variable.
  • Unknown differences.

The first category, irrelevant differences, do not affect computations and most likely do not affect the execution of function files.

The differences of the second category are usually because the authors of Octave decided on a better (subjective) implementation that the way Matlab does it, and so introduced “user preference variables” so that you can customize Octave’s behavior to be either Matlab-compatible or to use Octave’s new features. To make Octave more Matlab-compatible, put the following statements in your ~/.octaverc file, or use the command line option ‘–traditional’, which implies all of these settings. Note that this list may not be complete, because some new variables may have been introduced since this document was last updated.

PS1                           = ">> "
PS2                           = ""
beep_on_error                 = true
crash_dumps_octave_core       = false
default_save_format           = "mat-binary"
fixed_point_format            = true
page_screen_output            = false
print_empty_dimensions        = false
warn_function_name_clash      = false

The third category of differences is (hopefully) shrinking. If you find a difference between Octave behavior and Matlab, then you should send a description of this difference (with code illustrating the difference, if possible) to bug@octave.org.

An archive of old postings to the Octave mailing lists is maintained on ftp.che.wisc.edu in the directory /pub/octave/MAILING-LISTS.