{
"title": "ceil",
"category": "math/rounding",
"keywords": [
"ceil",
"rounding",
"digits",
"significant digits",
"gpu",
"like"
],
"summary": "Round scalars, vectors, matrices, or N-D tensors toward positive infinity or to specified digits.",
"references": [],
"gpu_support": {
"elementwise": true,
"reduction": false,
"precisions": [
"f32",
"f64"
],
"broadcasting": "matlab",
"notes": "Falls back to the host implementation when the active provider lacks unary_ceil."
},
"fusion": {
"elementwise": true,
"reduction": false,
"max_inputs": 1,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::math::rounding::ceil::tests",
"integration": "builtins::math::rounding::ceil::tests::ceil_gpu_provider_roundtrip"
},
"description": "`ceil(X)` rounds each element of `X` toward positive infinity, returning the smallest integer greater than or equal to the input. Optional arguments match MATLAB's extended syntax for rounding to fixed decimal places, significant digits, and prototype-based residency.",
"behaviors": [
"Works on scalars, vectors, matrices, and higher-dimensional tensors with MATLAB broadcasting semantics.",
"`ceil(X, N)` rounds toward positive infinity with `N` decimal digits (positive `N`) or powers of ten (negative `N`).",
"`ceil(X, N, 'significant')` rounds to `N` significant digits; `N` must be a positive integer.",
"Logical inputs are promoted to doubles (`false → 0`, `true → 1`) before applying the ceiling operation.",
"Character arrays are interpreted numerically (their Unicode code points) and return dense double tensors.",
"Complex inputs are rounded component-wise: `ceil(a + bi) = ceil(a) + i·ceil(b)`.",
"Non-finite values (`NaN`, `Inf`, `-Inf`) propagate unchanged.",
"Empty arrays return empty arrays of the appropriate shape.",
"Appending `'like', prototype` forces the result to match the residency of `prototype` (CPU or GPU). Prototypes must currently be numeric."
],
"examples": [
{
"description": "Rounding values up to the next integer",
"input": "x = [-2.7, -0.3, 0, 0.8, 3.2];\ny = ceil(x)",
"output": "y = [-2, 0, 0, 1, 4]"
},
{
"description": "Rounding a matrix up element-wise",
"input": "A = [1.2 4.7; -3.4 5.0];\nB = ceil(A)",
"output": "B = [2 5; -3 5]"
},
{
"description": "Rounding fractions upward in a tensor",
"input": "t = reshape([-1.8, -0.2, 0.4, 1.1, 2.1, 3.6], [3, 2]);\nup = ceil(t)",
"output": "up =\n [-1 2;\n 0 3;\n 1 4]"
},
{
"description": "Rounding up to two decimal places",
"input": "temps = [21.452 19.991 22.501];\nrounded = ceil(temps, 2)",
"output": "rounded = [21.46 20 22.51]"
},
{
"description": "Rounding to significant digits",
"input": "measurements = [0.001234 12.3456 98765];\nsig2 = ceil(measurements, 2, 'significant')",
"output": "sig2 = [0.0013 13.0 99000]"
},
{
"description": "Rounding complex numbers toward positive infinity",
"input": "z = [1.2 + 2.1i, -0.2 - 3.9i];\nresult = ceil(z)",
"output": "result = [2 + 3i, 0 - 3i]"
},
{
"description": "Keeping GPU results on-device with `unary_ceil`",
"input": "G = gpuArray([1.8 -0.2 0.0; -1.1 2.5 -3.4]);\nup = ceil(G);\ngather(up)",
"output": "ans =\n [ 2 0 0;\n -1 3 -3]"
},
{
"description": "Forcing GPU residency with a `'like'` prototype",
"input": "A = [1.8 -0.2; 2.7 3.4];\nproto = gpuArray(0);\nG = ceil(A, 'like', proto); % Result remains on the GPU\nresult = gather(G)",
"output": "result =\n [ 2 0;\n 3 4]"
}
],
"faqs": [
{
"question": "Does `ceil` always round toward positive infinity?",
"answer": "Yes—positive values round up away from zero, while negative values round toward zero (e.g., `ceil(-0.1) = 0`)."
},
{
"question": "How are complex numbers handled?",
"answer": "The real and imaginary parts are ceiled independently, matching MATLAB's component-wise definition."
},
{
"question": "Can I round to decimal digits or significant digits?",
"answer": "Yes. Use `ceil(X, N)` for decimal digits or `ceil(X, N, 'significant')` for significant digits. Negative `N` values round to powers of ten."
},
{
"question": "What happens with logical arrays?",
"answer": "Logical values promote to doubles (`0` or `1`) before rounding, so the outputs remain 0 or 1."
},
{
"question": "Can I pass character arrays to `ceil`?",
"answer": "Yes. Character data is treated as its numeric code points, producing a double tensor of the same size."
},
{
"question": "Do `NaN` and `Inf` values change?",
"answer": "No. Non-finite inputs propagate unchanged."
},
{
"question": "Will GPU execution change floating-point results?",
"answer": "No. Providers implement IEEE-compliant ceiling; when a provider lacks `unary_ceil`, RunMat falls back to the CPU to preserve MATLAB-compatible behaviour."
},
{
"question": "Does `'like'` work with `ceil`?",
"answer": "Yes. Append `'like', prototype` to request output that matches the prototype's residency. Currently prototypes must be numeric (scalars or dense tensors, host or GPU)."
},
{
"question": "Can fusion keep `ceil` on the GPU?",
"answer": "Yes. `ceil` participates in elementwise fusion, so fused graphs can stay resident on the device when supported."
}
],
"links": [
{
"label": "floor",
"url": "./floor"
},
{
"label": "round",
"url": "./round"
},
{
"label": "gpuArray",
"url": "./gpuarray"
},
{
"label": "gather",
"url": "./gather"
},
{
"label": "fix",
"url": "./fix"
},
{
"label": "mod",
"url": "./mod"
},
{
"label": "rem",
"url": "./rem"
}
],
"source": {
"label": "`crates/runmat-runtime/src/builtins/math/rounding/ceil.rs`",
"url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/math/rounding/ceil.rs"
},
"gpu_residency": "```matlab:runnable\nA = [1.8 -0.2; 2.7 3.4];\nproto = gpuArray(0);\nG = ceil(A, 'like', proto); % Result remains on the GPU\nresult = gather(G);\n```\n\nExpected output:\n\n```matlab\nresult =\n [ 2 0;\n 3 4]\n```",
"gpu_behavior": [
"When tensors already reside on the GPU, RunMat consults the active acceleration provider. If the provider implements the `unary_ceil` hook, `ceil(X)` executes entirely on the device and keeps tensors resident. When decimal or significant-digit rounding is requested—or when the provider lacks `unary_ceil`—RunMat gathers the tensor to host memory, applies the CPU implementation, and honours any `'like'` GPU prototype by uploading the result back to the device. This maintains MATLAB-compatible behaviour while exposing GPU acceleration whenever it is available."
]
}