RunMat
GitHub

ldivide — Compute element-wise left division in MATLAB and RunMat.

ldivide(A, B) (or A .\ B) divides each element of B by the corresponding element of A. Broadcasting, complex handling, and output-shape behavior follow MATLAB semantics.

Syntax

C = ldivide(A, B)
C = ldivide(A, B, "like", prototype)

Inputs

NameTypeRequiredDefaultDescription
AAnyYesLeft divisor operand.
BAnyYesRight dividend operand.
likeStringScalarYesLiteral string "like".
prototypeLikePrototypeYesOutput class/device prototype.

Returns

NameTypeDescription
CNumericArrayElementwise left quotient result.

Errors

IdentifierWhenMessage
RunMat:ldivide:InvalidArgumentOptional arguments are malformed or unsupported.ldivide: invalid argument
RunMat:ldivide:InvalidInputOperands or prototypes cannot be converted into supported numeric/logical forms.ldivide: invalid input
RunMat:ldivide:SizeMismatchOperands are not broadcast-compatible.ldivide: array sizes are not compatible for broadcasting
RunMat:ldivide:InternalProvider interaction, gather/upload, or internal tensor construction failed.ldivide: internal error

How ldivide works

  • Supports real, complex, logical, and character inputs; logical and character data are promoted to double precision before division.
  • Implicit expansion follows MATLAB rules: singleton dimensions expand automatically, while mismatched non-singleton extents raise MATLAB-compatible size errors.
  • Complex operands use the analytic continuation B ./ A, propagating NaN and Inf exactly as MATLAB does.
  • Empty shapes propagate cleanly—if the broadcasted output has a zero dimension, the result is empty with the expected shape.
  • Integer inputs promote to double precision, mirroring MATLAB’s numeric tower.
  • The optional 'like' prototype makes the result adopt the residency (host or GPU) and numeric flavour of the prototype. Complex prototypes are honoured on the host today; real gpuArray prototypes keep the result on the device.

Does RunMat run ldivide on the GPU?

When a gpuArray provider is active:

1. If both operands are gpuArrays with identical shapes, RunMat calls the provider’s elem_div hook with (B, A) so the division runs entirely on the GPU. 2. If the divisor A is scalar (host or device) and the numerator B is a gpuArray, the runtime uses scalar_div to evaluate B ./ a on device memory. 3. If the numerator B is scalar and the divisor A is a gpuArray, scalar_rdiv performs b ./ A without leaving the GPU. 4. When shapes require implicit expansion—or the provider lacks the necessary kernels—RunMat gathers to the host, computes the MATLAB-accurate result, then reapplies 'like' residency rules (including re-uploading to a gpuArray when requested). 5. The fusion planner treats ldivide as a fusible elementwise node, so adjacent elementwise producers and consumers can execute inside a single GPU pipeline or WGSL kernel, minimising redundant host↔device transfers.

GPU memory and residency

You usually do not need to call gpuArray manually. RunMat’s auto-offload planner keeps tensors on the GPU whenever provider kernels cover the operation. Explicit gpuArray / gather calls remain available for MATLAB compatibility; when a provider fallback happens, the runtime gathers to host, computes the MATLAB-accurate answer, and reapplies 'like' residency requests automatically.

Examples

Left-dividing a vector by a scalar

A = 2;
B = [4 6 8];
Q = ldivide(A, B)

Expected output:

Q = [2 3 4]

Broadcasting between column divisors and row numerators

A = (1:3)';         % column of divisors
B = [10 20 40];     % row of numerators
M = ldivide(A, B);  % implicit expansion

Expected output:

M =
   10.0000   20.0000   40.0000
    5.0000   10.0000   20.0000
    3.3333    6.6667   13.3333

Element-wise left division of complex values

A = [1+2i, 3-4i];
B = [2-1i, -1+1i];
Z = ldivide(A, B)

Expected output:

Z =
   0.0000 - 1.0000i   -0.2800 - 0.0400i

Dividing character codes by a scalar

A = 'ABC';
B = 2;
codes = ldivide(A, B)

Expected output:

codes = [0.0308 0.0303 0.0301]

Computing reciprocals with ldivide

A = [1 2 4 8];
B = 1;
R = ldivide(A, B);   % equivalent to 1 ./ A

Expected output:

R = [1 0.5 0.25 0.125]

Keeping results on the GPU with 'like'

proto = gpuArray.zeros(1, 1);
A = gpuArray([2 4 8 16]);
B = gpuArray([4 8 16 32]);
deviceResult = ldivide(A, B, 'like', proto);
hostCheck = gather(deviceResult)

Expected output:

deviceResult =
  1x4 gpuArray
    2  2  2  2
hostCheck = [2 2 2 2]

Using ldivide with coding agents

Open a RunMat example with live inputs, then ask the agent to explain how ldivide changes the result.

Run a small ldivide example, explain the result, then change one input and compare the output.

FAQ

Does ldivide support MATLAB implicit expansion?

Yes. Singleton dimensions expand automatically; otherwise incompatible shapes raise MATLAB-style errors.

What numeric type does ldivide return?

Real inputs return doubles; mixed or complex inputs return complex doubles. Logical and character inputs promote to double before division.

How does ldivide handle division by zero?

finite ./ 0 yields signed infinities, and 0 ./ 0 becomes NaN, matching MATLAB and IEEE-754 behaviour.

Can I divide gpuArrays by host scalars?

Yes. Numeric scalars stay on device through scalar_div/scalar_rdiv. Non-numeric host scalars trigger a gather-then-divide fallback.

Does ldivide preserve gpuArray residency after a fallback?

If the runtime gathers to host (for example, due to implicit expansion), the intermediate stays on the host. Later computations may move it back when auto-offload deems it profitable, or you can request GPU residency explicitly with 'like'.

How do I keep the result on the GPU?

Provide a real gpuArray prototype: ldivide(A, B, 'like', gpuArray.zeros(1,1)). The runtime re-uploads the host result when necessary.

How are empty arrays handled?

Empty operands propagate cleanly—the output shape is the broadcasted shape, and the data vector is empty.

Are integers and logicals supported?

Yes. Both promote to double precision before division so you get MATLAB-compatible numeric results (including Inf when dividing by zero).

Can I mix real and complex operands?

Absolutely. Mixed cases return complex doubles with full MATLAB semantics.

Elementwise

abs · angle · complex · conj · double · exp · expm1 · factorial · gamma · heaviside · hypot · imag · log · log10 · log1p · log2 · minus · nextpow2 · plus · pow2 · power · rdivide · real · sign · single · sqrt · times

Trigonometry

acos · acosh · asin · asinh · atan · atan2 · atanh · cos · cosd · cosh · deg2rad · rad2deg · sin · sind · sinh · tan · tand · tanh

Reduction

all · any · cummax · cummin · cumprod · cumsum · cumtrapz · diff · gradient · max · mean · median · min · nnz · prod · std · sum · trapz · var

Rounding

ceil · fix · floor · mod · rem · round

Factor

chol · eig · lu · qr · svd

Solve

cond · det · inv · linsolve · norm · null · pinv · rank · rcond · rref

Symbolic

digits · int · limit · sym · syms · vpa

Fft

fft · fft2 · fftshift · ifft · ifft2 · ifftshift

Interpolation

interp1 · interp2 · pchip · ppval · spline

Ode

ode15s · ode23 · ode45

Open-source implementation

Unlike proprietary runtimes, every RunMat function is open-source. Read exactly how ldivide is executed, line by line, in Rust.

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.

Getting started · Benchmarks · Pricing

Download RunMat

Download RunMat for full performance, or use RunMat in your browser for zero setup.