diag — Create diagonal matrices or extract diagonals in MATLAB and RunMat.
diag either constructs a diagonal matrix from a vector or extracts a diagonal from a matrix. The four public forms, offset handling, input classes, and GPU residency follow MATLAB semantics; additional size, vector, class, and like forms are named RunMat-only extensions.
Syntax
D = diag(v)
D = diag(v, k)
x = diag(A)
x = diag(A, k)Inputs
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
A | Any | Yes | — | Input scalar, vector, or matrix. |
k | NumericScalar | Yes | — | Diagonal offset index. |
Returns
| Name | Type | Description |
|---|---|---|
B | Any | Diagonal matrix or diagonal vector extracted from the input. |
Errors
| Identifier | When | Message |
|---|---|---|
RunMat:diag:InvalidInput | Input type, option grammar, size override, or output conversion is invalid. | diag: invalid input argument |
RunMat:diag:InvalidOffset | Diagonal offset is not a finite integer scalar. | diag: invalid diagonal offset |
How diag works
diag(v)with a vectorvreturns a square matrix whose main diagonal isv.diag(v, k)placesvon thek-th diagonal: super-diagonals fork > 0, sub-diagonals fork < 0. The output size grows byabs(k).diag(A)with a matrixAreturns a column vector containing the main diagonal ofA.diag(A, k)extracts thek-th diagonal. When the requested diagonal does not exist, an empty column vector is returned.- RunMat mode additionally supports
diag(v, 'vector'), explicit rectangular sizes, output-class overrides, and'like'prototypes; each extension rejects independently in MATLAB-compatible mode. - Logical inputs stay logical; complex inputs stay complex; character arrays preserve padding with spaces off the diagonal.
- MATLAB-compatible mode rejects every input with more than two dimensions. RunMat mode retains trailing-singleton support as a named extension.
Does RunMat run diag on the GPU?
When a compatible real or logical input lives on the GPU, RunMat calls its owning acceleration provider's diag_from_vector, diag_from_vector_sized, diag_extract, or metadata-only reshape hook as appropriate. That covers native vector-to-matrix placement, explicit rectangular size overrides, 'vector' mode, matrix diagonal extraction, and empty out-of-bounds diagonals without gathering. Missing hooks and complex or conversion-heavy forms use an owner-resolved gather, host computation, and validated re-upload, so the result remains on the originating provider and device. A resident GPU 'like' prototype deliberately selects the prototype's owner and device instead.
GPU memory and residency
You usually do NOT need to call gpuArray yourself in RunMat (unlike MATLAB).
In RunMat, the auto-offload planner keeps residency on the GPU when expressions make use of GPU providers. For diag, compatible real and logical GPU inputs use the owning provider's diagonal hooks. If a hook is missing or the requested storage/class semantics require host evaluation, RunMat gathers through that owner, computes the result on the host, and validates a re-upload to the same owner and device. A GPU 'like' prototype instead selects its own registered owner and device for the validated result.
To preserve backwards compatibility with MathWorks MATLAB, and for when you want to explicitly bootstrap GPU residency, you can call gpuArray to move data to the GPU. That mirrors MATLAB's behaviour while still allowing RunMat's planner to decide whether the GPU offers an advantage for the surrounding computation.
Since MathWorks MATLAB does not have a fusion planner, and they kept their parallel execution toolbox separate from the core language, as their toolbox is a separate commercial product, MathWorks MATLAB users need to call gpuArray to move data to the GPU manually whereas RunMat users can rely on the fusion planner to keep data on the GPU automatically.
Examples
Creating a diagonal matrix from a vector
v = [4 5 6];
D = diag(v)Expected output:
D =
4 0 0
0 5 0
0 0 6Placing a vector on an upper diagonal
v = [1 2 3];
U = diag(v, 1)Expected output:
U =
0 1 0 0
0 0 2 0
0 0 0 3
0 0 0 0Extracting a subdiagonal as a column vector
A = [1 2 3; 4 5 6; 7 8 9];
d = diag(A, -1)Expected output:
d =
4
8Building a diagonal matrix from a logical mask
mask = logical([1 0 1 0]);
M = diag(mask)Expected output:
M =
1 0 0 0
0 0 0 0
0 0 1 0
0 0 0 0Keeping diagonal results on the GPU
G = gpuArray([2; 4; 8]);
D = diag(G);
firstTwo = gather(D(1:2, 1:2))Expected output:
firstTwo =
2 0
0 4Returning a vector without creating a matrix
v = [10 20 30];
d = diag(v, 'vector')Expected output:
d =
10
20
30Creating a rectangular diagonal matrix with sz
v = [1 2];
R = diag(v, [2 4])Expected output:
R =
1 0 0 0
0 2 0 0Matching residency and type with 'like'
G = gpuArray([1 3 5]');
D = diag([1 2 3], 'like', G)Using diag with coding agents
Open a RunMat example with live inputs, then ask the agent to explain how diag changes the result.
Run a small diag example, explain the result, then change one input and compare the output.
FAQ
Does diag always return a square matrix?⌄
The public vector form returns a square matrix. RunMat mode offers separately gated 'vector' and explicit-size extensions for column-vector and rectangular results.
What happens if I request a diagonal outside the matrix bounds?⌄
You receive an empty column vector with size 0 × 1, matching MATLAB's behaviour.
Can I use diag with logical or character arrays?⌄
Yes. Logical inputs produce logical outputs, and character inputs produce padded character arrays with spaces away from the diagonal.
Does diag support complex numbers?⌄
Complex inputs are supported. The output keeps the real and imaginary parts intact.
How do offsets work with vectors?⌄
diag(v, k) grows the matrix by abs(k) and shifts the diagonal up (k > 0) or down (k < 0).
Can I place a diagonal inside a non-square matrix?⌄
RunMat mode can do this through the gated explicit-size extension, such as diag(v, [m n]) or diag(v, k, [m n]); these are not public MATLAB diag forms.
What if the vector is empty?⌄
diag([]) returns a 0 × 0 matrix. diag([], k) returns a square matrix of size abs(k) filled with zeros.
Do GPU results stay on the device?⌄
Yes. Validated provider hooks serve compatible real and logical paths. Exact integer and complex inputs use an exact gather and owner-preserving re-upload when native hooks cannot preserve their storage contract.
Is the offset argument required to be an integer?⌄
Yes. Non-integer or non-finite offsets raise an error.
Does diag modify the original input?⌄
No. It always returns a new array, leaving the input unchanged.
How do I match another array's type or residency?⌄
RunMat mode provides a separately gated 'like' extension. Logical, complex, integer, and GPU prototypes are respected even when computation uses an exact host fallback.
Is single precision supported?⌄
Yes. Native single input preserves single output, and RunMat extension mode can request single output with a single-precision 'like' prototype.
Related Array functions
Shape
blkdiag · cat · circshift · flip · fliplr · flipud · horzcat · ipermute · kron · permute · repelem · repmat · reshape · rot90 · squeeze · toeplitz · tril · triu · vertcat
Grouping
accumarray · combinations · discretize · findgroups · groupcounts · grp2idx · splitapply
Sorting Sets
argsort · intersect · ismember · ismembertol · issorted · issortedrows · setdiff · setxor · sort · sortrows · union · unique
Open-source implementation
Unlike proprietary runtimes, every RunMat function is open-source. Read exactly how diag is executed, line by line, in Rust.
- View the source for diag in Rust on GitHub
- Learn how the RunMat runtime works
- Found a bug? Open an issue with a minimal reproduction.
About RunMat
RunMat is an open-source runtime that executes MATLAB-syntax code blazing on any GPU. It is licensed under the Apache 2.0 license.
- RunMat automatically optimizes your math for GPU execution on Apple, Nvidia, and AMD hardware. No code changes needed. Simulations that took hours now take minutes.
- Start running code in seconds. RunMat runs in the browser, on the desktop, or from the CLI. No license server, no IT ticket.