What does the ldivide function do in MATLAB / RunMat?
ldivide(A, B) (operator form A .\ B) divides each element of B by the corresponding element of A, delivering MATLAB-compatible left-division semantics. It is equivalent to B ./ A but keeps argument order consistent with MATLAB source code and operator precedence.
How does the ldivide function behave in MATLAB / RunMat?
- 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, propagatingNaNandInfexactly 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.
ldivide Function GPU Execution Behaviour
When a gpuArray provider is active:
- If both operands are gpuArrays with identical shapes, RunMat calls the provider’s
elem_divhook with(B, A)so the division runs entirely on the GPU. - If the divisor
Ais scalar (host or device) and the numeratorBis a gpuArray, the runtime usesscalar_divto evaluateB ./ aon device memory. - If the numerator
Bis scalar and the divisorAis a gpuArray,scalar_rdivperformsb ./ Awithout leaving the GPU. - 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). - The fusion planner treats
ldivideas 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.
Examples of using the ldivide function in MATLAB / RunMat
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]
GPU residency in RunMat (Do I need gpuArray?)
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.
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.
See Also
times, rdivide, mldivide, gpuArray, gather
Source & Feedback
- Implementation:
crates/runmat-runtime/src/builtins/math/elementwise/ldivide.rs - Found a bug or behavioural difference? Please open an issue with details and a minimal repro.