MATLAB — Reference

Source: https://www.mathworks.com/help/matlab/

MATLAB

  • Created: late 1970s by Cleve Moler at the University of New Mexico as a Fortran teaching aid for LINPACK/EISPACK; commercialised as MathWorks in 1984 by Moler, Jack Little, and Steve Bangert.
  • Latest stable: R2025a (general release 2025-03-19); R2024b (2024-09-11) is the prior long-lifetime release. MathWorks ships two named releases per year: aR (March) and bR (September).
  • Owner / license: proprietary, MathWorks Inc. (Natick, MA). Commercial single-user perpetual license ~$2,150 (Industry, base MATLAB only); annual ~$940. Toolboxes ~$500–$3,400 each. Home $149, Student $49–$99, MATLAB Online (cloud) bundled with most licenses; MATLAB Online Server ~$1,000/yr add-on for self-hosting.
  • Paradigms: array-oriented, imperative, procedural; OO since R2008a (handle + value classes); functional flavour via function handles + anonymous functions.
  • Typing: dynamic, weak coercion between numerics; default numeric is double (IEEE 754 binary64). Optional argument validation (arguments block, since R2019b) gives near-static signatures.
  • Memory: reference-counted with copy-on-write for value semantics; manual clear, automatic on function return. Handle classes are reference types.
  • Compilation: interpreted with a JIT (the “execution engine”; rewritten with LLVM-based tiered JIT in R2015b+). Standalone deployment via MATLAB Compiler (bundles runtime) or MATLAB Coder (true C/C++ codegen).
  • Primary domains: numerical linear algebra, signal/image processing, controls, model-based design (Simulink), communications, computational finance, computational biology, MBSE, automated driving, RF/antenna, deep learning research.
  • Official docs: https://www.mathworks.com/help/matlab/

At a glance

MATLAB is a numerical-computing environment built around the matrix as the primitive type — every scalar is implicitly a 1x1 matrix. Arrays are 1-indexed, column-major (Fortran order), and implicitly broadcast via “implicit expansion” (since R2016b, replacing the older bsxfun idiom). The language is inseparable from its IDE: editor + debugger + workspace browser + plot windows + variable inspector + profiler. Simulink (the graphical block-diagram environment) and ~100 toolboxes turn MATLAB into a vertical-stack engineering tool used heavily in aerospace, automotive, biotech, and academia. The cost is a per-seat per-toolbox proprietary license with network or activation-based seat management.

Getting started

Install: download from https://www.mathworks.com/downloads/ — requires a MathWorks Account and an active license (Individual, Network/Concurrent, or Campus-Wide). The installer offers per-toolbox selection. MATLAB Online (browser, https://matlab.mathworks.com) runs the same release with most toolboxes preinstalled — no install required.

Open-source alternative: GNU Octave (octave.org, 9.x as of 2025) is ~90% syntax-compatible for core language + scripts; toolbox APIs (Simulink, Stateflow, App Designer) are not compatible. Use --traditional for closer MATLAB behaviour. FreeMat and Scilab (Inria, BSD-3) are looser alternatives.

Hello world:

disp('Hello, world!')

Run: matlab -batch "script_name" (headless, since R2019a) or open in the IDE and press F5. Script files end in .m; live notebooks end in .mlx (Live Scripts — markdown-like cells with inline output).

Project layout (a toolbox/project):

MyProject/
  MyProject.prj          % MATLAB Project file (R2019a+)
  +mypkg/                % package namespace (the + prefix)
    foo.m
    Bar.m
  @MyClass/              % class folder (alternative to single-file class)
    MyClass.m
    method1.m
  tests/
    tMyClass.m           % MATLAB Test Framework
  docs/
  resources/

Package manager: Add-On Explorer (in-IDE, GUI) is the official package mechanism — installs FileExchange submissions, Hardware Support Packages, and toolboxes. Programmatic install via matlab.addons.install(path). Community alternative: mpm (https://github.com/mobeets/mpm) for git-based package mgmt. No pip/npm equivalent in core MATLAB.

REPL: the Command Window is interactive — every statement evaluates immediately, suppressed with trailing ;. Workspace variables persist until clear. Tab completion, help fn, doc fn (opens browser-style docs).

Basics

Primitives: double (default, IEEE 754 binary64), single, int8/16/32/64, uint8/16/32/64, logical, char (UTF-16 code unit), string (since R2016b — preferred over char for text), cell (heterogeneous container), struct (named-field record), function_handle (@f), categorical, datetime, duration, table, timetable.

x = 3.14;          % double, 1x1
A = [1 2; 3 4];    % 2x2 double matrix
v = 1:0.5:5;       % row vector 1..5 step 0.5
s = "hello";       % string scalar (R2016b+)
c = 'hello';       % char row vector (legacy)

Variables / scope: dynamic typing, function-local by default. Workspaces are isolated per function call; the base workspace is the Command Window. global var and persistent var modify scope. Variables created at first assignment.

Control flow: if/elseif/else/end, for k = 1:n, while, switch/case/otherwise/end, break, continue, return. No do-while. try/catch ME for exceptions (ME is a MException object). Short-circuit && and ||; element-wise & and |.

for k = 1:numel(xs)
    if xs(k) > 0
        ys(k) = sqrt(xs(k));
    end
end

Functions: one function per file is the traditional rule (file name = function name); local functions (since R2016b in scripts) and nested functions (with shared workspace) are common. Anonymous: f = @(x,y) x.^2 + y;. Multiple return values via [a,b,c] = fn(...). Ignored outputs with ~. Variable args via varargin/varargout, named via nargin/nargout.

function [mu, sigma] = stats(x)
    arguments
        x (1,:) double {mustBeFinite}   % size + class + validator
    end
    mu = mean(x);
    sigma = std(x);
end

The arguments block (R2019b+) gives type/size validation, default values, and per-arg validators — the modern way to write robust APIs.

Strings: double-quoted string arrays ("hello") vs single-quoted char arrays ('hello'). Concatenation: "a" + "b" (string), ['a','b'] (char). Formatted: sprintf("%.2f", pi). Multiline: triple-quote since R2024a ("""...""").

Built-in arrays / containers: [ ... ] matrix literal, { ... } cell literal, struct('a',1,'b',2), containers.Map (legacy hash), dictionary (R2022b+, preferred), table (column-oriented dataframe).

T = table((1:3)', ["a";"b";"c"], 'VariableNames', ["id" "name"]);
d = dictionary("apple", 1, "banana", 2);

Intermediate

Operators and broadcasting:

  • *, /, \ are matrix ops (x = A\b solves Ax = b via the appropriate factorisation chosen by mldivide).
  • .*, ./, .\, .^ are elementwise.
  • Implicit expansion (since R2016b): A - mean(A) automatically broadcasts the mean over rows. Pre-2016b required bsxfun(@minus, A, mean(A)).
  • Logical indexing: xs(xs > 0) = 0. Linear indexing into matrices: A(5) reads column-major.

Type system / classes: OO via classdef (since R2008a). Two flavours:

  • Value classes — copy-on-assign, like struct.
  • Handle classes (< handle) — reference semantics, support events/listeners, used for GUI widgets and resources.
classdef Counter < handle
    properties
        count (1,1) double = 0
    end
    methods
        function inc(obj, n)
            arguments
                obj
                n (1,1) double = 1
            end
            obj.count = obj.count + n;
        end
    end
end

Packages and namespaces: a directory starting with + is a package. +mypkg/foo.m is mypkg.foo. Import with import mypkg.foo.

Error handling: error("MyApp:badInput", "x must be %d", n) throws an MException. try ... catch ME ... end. ME.identifier, ME.message, ME.stack. rethrow(ME), throwAsCaller(ME) for clean stacks. assert(cond, msg) for invariants.

Concurrency / parallelism (Parallel Computing Toolbox required for most):

  • parfor k = 1:N — parallel for-loop on a local pool (parpool('local')) or cluster (MATLAB Parallel Server).
  • parfeval(p, fn, nargout, args...) — async future returning a parallel.FevalFuture.
  • spmd ... end — Single Program Multiple Data block, one execution per worker.
  • gpuArray(A) — move data to GPU; most ops dispatch automatically.
  • distributed(A) — partitioned across cluster workers.
  • tall(A) — out-of-core arrays for data larger than RAM (deferred evaluation, executed on demand).
  • backgroundPool (R2021b+) — thread-based parallelism without the toolbox (limited operations).

I/O:

  • load/save for .mat files (HDF5-based since v7.3, prior versions are custom).
  • readtable/writetable (csv, xls, parquet), readmatrix, readstruct (JSON since R2023b), readstring.
  • fopen/fread/fwrite/fclose for low-level binary.
  • webread/webwrite for HTTP, websocket for WS (R2024a+).

Stdlib / built-in highlights: mean, std, var, corr, fft, ifft, eig, svd, lu, qr, chol, linsolve, mldivide (\), interp1/interp2, polyfit, ode45/ode23s/ode15s (Runge-Kutta + stiff solvers), integral, fzero, fminsearch, regexp, datetime, histogram, plot/plot3/surf/mesh.

Advanced

Memory model: value semantics with copy-on-write — assignment and function-argument passing copy the reference, and the actual buffer is duplicated only on first mutation. Handle classes (< handle) opt out and use pointer semantics. In-place operations require special care: x = x + 1 is in-place if x has refcount 1 and the JIT can prove it; otherwise a copy is made. The tic/toc + profile on/profile viewer workflow is the standard way to find allocation hotspots.

Parallel deep dive:

  • Workers are MATLAB processes connected via the parallel.Pool API; communication is over shared memory or TCP.
  • MATLAB Parallel Server (formerly MATLAB Distributed Computing Server) scales parpool to clusters managed by MJS (MathWorks Job Scheduler), Slurm, PBS, LSF, HTCondor, AWS, Azure.
  • parfor constant restriction: loop iterations must be independent and ordering-agnostic; “broadcast variables” are sent once, “sliced variables” are partitioned; “reduction variables” are combined commutatively.
  • GPU: gpuArray(A) ports the array to CUDA; over 1,000 functions dispatch on gpuArray. Multi-GPU via parfor + gpuDevice(k) to pin each worker.
  • Threading: core MATLAB is single-threaded per worker but many built-ins (BLAS, FFT, image ops) are internally multi-threaded via Intel MKL / oneMKL.

FFI / interop:

  • MEX — write C, C++, or Fortran functions callable from MATLAB. Compiled via mex foo.c. The modern C++ API (since R2018a) uses the matlab::data::Array class hierarchy. loadlibrary for raw shared-library calls.
  • Python: py.module.fn(args) calls Python in-process (CPython embedded). Configure via pyenv. Conversions: py.list, py.dict. Since R2024a, MATLAB ships its own Python environment by default.
  • Java: JVM embedded; import java.util.* works. Used heavily by Toolboxes (e.g., XML parsing, Database Toolbox).
  • .NET: NET.addAssembly(path) then call .NET classes directly (Windows only).
  • C++ / shared lib generation: MATLAB Coder generates portable C/C++ from a restricted subset of MATLAB. GPU Coder generates CUDA. HDL Coder generates VHDL/Verilog (for FPGAs and ASICs). MATLAB Compiler SDK packages MATLAB code as C/C++/Java/.NET/Python libraries; MATLAB Production Server hosts them as a request-response service.

Reflection: whos lists workspace contents with types and sizes. class(x), isa(x, "double"), properties(obj), methods(obj), metaclass(obj) (returns a meta.class object — full reflection of the class tree). functions(@fn) introspects a function handle.

Performance tools:

  • tic / toc — quick wall-clock timing.
  • timeit(@() fn(x)) — robust microbench (warmup, multiple runs, returns median).
  • profile on; ...; profile viewer — line-level profiler with call graph.
  • Run and Time button in the Editor.
  • Code Analyzer (“M-Lint”) — static checker, displays warnings inline; CLI: checkcode.

God mode

Function handles + closures: @(x) x.^2 + a captures a by value at handle-creation time. Powers ODE solvers (ode45(@rhs, tspan, y0)), optimisers (fminunc(@cost, x0)), and event-driven Apps.

makeCounter = @() local_counter();
function c = local_counter()
    count = 0;
    c.inc = @() count_inc();
    c.get = @() count;
    function count_inc(), count = count + 1; end
end

Operator overloading: define plus, minus, mtimes, times, subsref, subsasgn, end, numel, size, disp, display, eq, ne, lt, gt, le, ge, colon, horzcat, vertcat, cat on a classdef. subsref/subsasgn give full control over obj.x, obj{k}, obj(i,j) indexing.

Metaclass system: meta.class.fromName("MyClass") returns a fully introspectable object — properties, methods (with signatures), events, superclasses, attributes (Sealed, Abstract, Hidden). Used by matlab.unittest.TestRunner, App Designer, and code generators.

Events / listeners (handle classes): addlistener(obj, "EventName", @cb) for the observer pattern; powers App Designer.

Code generation pipelines:

  • MATLAB Coder — generates ANSI C / C++ from a function and a “build entry point”. Subset: no cell, no dynamic class creation, no eval. Output is portable and embeddable.
  • GPU Coder — same idea, emits CUDA kernels; supports cuDNN, cuBLAS, TensorRT integration for deployed deep nets.
  • HDL Coder — fixed-point MATLAB / Simulink → synthesisable VHDL/Verilog for Xilinx / Intel FPGAs.
  • Simulink Coder + Embedded Coder — Simulink models → C for automotive ECUs (AUTOSAR), aerospace controllers (DO-178), motor controllers.

Live Scripts (.mlx): XML-zipped notebook format; cells mix code, formatted text, equations (LaTeX), images, interactive controls (uislider, uidropdown). Export to PDF, HTML, LaTeX, Markdown.

App Designer: drag-and-drop GUI builder generating classdef files; replaces the older GUIDE (deprecated and removed in R2025b). Apps are first-class deployable artefacts via MATLAB Compiler.

Simulink + Stateflow + Simscape:

  • Simulink — graphical block-diagram tool for dynamical systems (signals + states). Solver-driven, fixed- or variable-step, supports HIL/SIL/PIL.
  • Stateflow — hierarchical finite-state machines embedded in Simulink.
  • Simscape — physical-network modelling (mechanical, electrical, hydraulic, thermal, multidomain). Includes Simscape Electrical, Multibody, Fluids, Driveline.

Idioms & style

  • Vectorise over loops: y = sin(x).^2 + cos(x).^2 not for k=1:N, y(k) = sin(x(k))^2 + cos(x(k))^2; end. The JIT closes much of the gap, but vectorised code is also more readable.
  • Preallocate: y = zeros(N,1); before a loop that fills it — growing arrays inside a loop is O(N^2).
  • end keyword in indexing: xs(end) is the last, xs(end-2:end) is the last three. Works inside any indexing expression.
  • ~ for ignored outputs: [~, idx] = max(xs);.
  • Anonymous function handles for callbacks and closures: arrayfun(@(x) x.^2, xs).
  • Naming: lowerCamelCase for functions/vars (fitModel, meanSquaredError); PascalCase for classes; i_* or t_* prefix for test files (per MathWorks internal style, but no enforced standard).
  • Formatter: built-in Smart Indent (Ctrl+I); no canonical formatter like Black exists. Community: MBeautifier (https://github.com/davidvarga/MBeautifier).
  • Linter: built-in Code Analyzer flags warnings inline. CLI: checkcode foo.m.
  • Doc strings: the first comment block under a function definition is the help text shown by help fn. Use % See also: ... to cross-link.
  • What reviewers flag: growing arrays in loops, missing arguments blocks on public functions, eval/evalin/assignin (anti-pattern), i or j used as loop var (shadows sqrt(-1)), single-quoted 'char' strings on new code (prefer "string"), forgotten ; causing screen spam, leaking handles in long sessions.

Ecosystem

Toolboxes (~100 total, sample of widely-used):

DomainToolbox
SignalSignal Processing, DSP System, Wavelet, Audio, Phased Array, RF
ImageImage Processing, Computer Vision, Lidar, Hyperspectral Imaging
Stats / ML / DLStatistics & Machine Learning, Deep Learning, Reinforcement Learning, Predictive Maintenance, Text Analytics
OptimisationOptimization, Global Optimization, Symbolic Math, Curve Fitting
ControlControl System, Robust Control, System Identification, Model Predictive Control
ModellingSimulink, Stateflow, Simscape, Simulink Real-Time
Code genMATLAB Coder, GPU Coder, HDL Coder, Embedded Coder, Fixed-Point Designer
VerificationSimulink Test, Requirements Toolbox, Polyspace Bug Finder / Code Prover
Robotics / autoRobotics System, Navigation, ROS, UAV, Automated Driving, Vehicle Dynamics
Comms / RFCommunications, 5G, WLAN, Bluetooth, Satellite Communications, Antenna
Bio / medBioinformatics, SimBiology, Medical Imaging
Web / cloudMATLAB Production Server, MATLAB Web App Server, MATLAB Parallel Server
FinanceFinancial, Risk Management, Econometrics, Datafeed

Community resources:

Notable users: NASA (Mars rovers, JWST flight software dev), Lockheed Martin, Boeing, Airbus, Ford, GM, Toyota, Bosch (model-based dev for ECUs), Mercedes (AMG), Goldman Sachs (quant analytics), Pfizer / Novartis (SimBiology PK/PD), MIT, Stanford, every major engineering university for teaching.

Related references: fortran (the LINPACK heritage), julia (open-source successor in numerical computing), python + NumPy/SciPy (open-source alternative for many MATLAB workflows), scientific (other numerical languages), hdl (HDL Coder targets).

Gotchas

  • 1-indexing trips Python/C users — xs(1) is the first, xs(0) errors.
  • Column-major storage — A(:) flattens column-by-column. Affects MEX, file I/O with fwrite, and interop with row-major C/NumPy.
  • double default1/3 is double even when both args are int. int32(1)/int32(3) returns 0 (integer division, rounded).
  • Copy semantics on argument passing — modifying an arg inside a function does not affect the caller (unless the class extends handle). The JIT optimises so the copy is free if you don’t mutate.
  • i and j as loop vars shadow the imaginary unit. Use ii, kk, or 1i explicitly. R2025a now warns on this.
  • eval is evil — slow, unsafe, breaks the Code Analyzer’s data-flow. Same for evalin, assignin. Almost always replaceable with dictionary lookups or function handles.
  • parfor constant restrictions: “iterator must be a for ranging over 1:N,” variables must be classifiable as broadcast/sliced/reduction/temporary; disp inside parfor interleaves output unpredictably; you cannot read globals or use figure inside.
  • Cell vs struct vs table confusion — cell is for heterogeneous lists, struct for named fields, table for tabular data with column names + types. Modern code: prefer table/dictionary over containers.Map.
  • License-server hiccups — Industry licenses check out features from a FlexNet server; intermittent network or VPN drops cause “License checkout failed” mid-session. License Manager Log is the diagnostic. Concurrent licenses count seats, not users — a single user across two machines uses two seats.
  • fprintf to stdout vs file: fprintf('hi\n') writes to stdout; fprintf(fid, ...) writes to file fid. The first-arg ambiguity bites.
  • String vs char: 'a' == 'a' is 1 (logical scalar — char equality element-wise). "a" == "a" is 1 (logical scalar — string equality). But "abc" == 'abc' errors on size mismatch. Use strcmp/isequal for portable comparison.
  • Hidden state in handle classes — passing the same handle to two callers means both can mutate it; debug by checking isa(x, 'handle').
  • clear classes is heavy — drops all loaded classes, breaks any open Apps; prefer clear x y z for targeted resets.
  • save -v7.3 uses HDF5 and supports >2 GB variables and partial-load via matfile; older -v6/-v7 cannot.
  • R-numbering surpriseR2024a came before R2024b. Release lifetimes: each named release receives bug-fix updates Update 1..N for ~2 years; LTS-style “Sustained Engineering” extends critical fixes longer for some.

Citations