runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "logical",
  "category": "logical",
  "keywords": [
    "logical",
    "boolean conversion",
    "truth mask",
    "gpuArray",
    "mask array"
  ],
  "summary": "Convert scalars, arrays, and gpuArray values to MATLAB-compatible logical values.",
  "references": [],
  "gpu_support": {
    "elementwise": true,
    "reduction": false,
    "precisions": [
      "f32",
      "f64"
    ],
    "broadcasting": "matlab",
    "notes": "Prefers a device-side elem\\_ne(X, 0) cast when the provider supports elem_ne and zeros_like; otherwise gathers to the host, converts, and re-uploads the logical result."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 1,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::logical::ops::tests",
    "integration": "builtins::logical::ops::tests::logical_gpu_roundtrip"
  },
  "description": "`logical(X)` converts numeric, logical, character, and gpuArray inputs into MATLAB logical values (booleans). Any non-zero (or `NaN`/`Inf`) element maps to `true`, while zero maps to `false`. Logical inputs are returned unchanged.",
  "behaviors": [
    "`logical` accepts scalars, dense arrays, N-D tensors, and gpuArrays. Shapes are preserved bit-for-bit.",
    "Non-zero numeric values, `NaN`, and `Inf` map to `true`; `0` and `-0` map to `false`.",
    "Complex inputs are considered `true` when either the real or imaginary component is non-zero.",
    "Character arrays are converted elementwise by interpreting code points (so `'A'` becomes `true`, `'\\0'` becomes `false`).",
    "Strings, structs, cells, objects, and other non-numeric types raise MATLAB-compatible errors (`\"Conversion to logical from <type> is not possible\"`).",
    "Scalar results become logical scalars (`true`/`false`); higher-rank arrays produce dense logical arrays."
  ],
  "examples": [
    {
      "description": "Creating a logical mask from numeric data",
      "input": "values = [0 2 -3 0];\nmask = logical(values)",
      "output": "mask =\n  1×4 logical array\n     0     1     1     0"
    },
    {
      "description": "Building a logical mask from a matrix",
      "input": "M = [-4 0 8; 0 1 0];\nmask = logical(M)",
      "output": "mask =\n  2×3 logical array\n     1     0     1\n     0     1     0"
    },
    {
      "description": "Treating NaN and Inf values as true",
      "input": "flags = logical([NaN Inf 0])",
      "output": "flags =\n  1×3 logical array\n     1     1     0"
    },
    {
      "description": "Converting complex numbers to logical scalars",
      "input": "z = logical(3 + 4i);\nw = logical(0 + 0i)",
      "output": "z =\n     1\nw =\n     0"
    },
    {
      "description": "Converting character arrays to logical values",
      "input": "chars = ['A' 0 'C'];\nmask = logical(chars)",
      "output": "mask =\n  1×3 logical array\n     1     0     1"
    },
    {
      "description": "Keeping gpuArray inputs on the device",
      "input": "G = gpuArray([0 1 2]);\nmaskGPU = logical(G);\nhostMask = gather(maskGPU)",
      "output": "hostMask =\n  1×3 logical array\n     0     1     1"
    },
    {
      "description": "Preserving empty shapes through logical conversion",
      "input": "emptyVec = zeros(0, 3);\nlogicalEmpty = logical(emptyVec)",
      "output": "logicalEmpty =\n  0×3 logical array\n     []"
    }
  ],
  "faqs": [
    {
      "question": "Which input types does `logical` support?",
      "answer": "Numeric, logical, complex, character, and gpuArray values are accepted. Strings, structs, cells, objects, and function handles are rejected with MATLAB-compatible error messages."
    },
    {
      "question": "How are NaN or Inf values treated?",
      "answer": "They evaluate to `true`. MATLAB defines logical conversion as “non-zero”, and `NaN` / `Inf` both satisfy that rule."
    },
    {
      "question": "How does `logical` handle complex numbers?",
      "answer": "The result is `true` when either the real or imaginary component is non-zero (or `NaN`/`Inf`). Only `0 + 0i` converts to `false`."
    },
    {
      "question": "Does the builtin change array shapes?",
      "answer": "No. Shapes are preserved exactly, including empty dimensions and higher-rank tensors."
    },
    {
      "question": "What happens to existing logical arrays?",
      "answer": "They are returned verbatim. Logical gpuArrays remain on the device without triggering new allocations."
    },
    {
      "question": "Can I convert strings with `logical`?",
      "answer": "No. MATLAB rejects string inputs, and RunMat mirrors that behaviour: `\"logical: conversion to logical from string is not possible\"`."
    },
    {
      "question": "What about structs, cells, or objects?",
      "answer": "They raise the same conversion error as MATLAB. Use functions like `~cellfun(@isempty, ...)` to derive masks instead."
    },
    {
      "question": "Does the GPU path allocate new buffers?",
      "answer": "Only when the provider cannot operate in-place. The preferred path performs `elem_ne` against a zero tensor and reuses the resulting buffer. Fallback paths allocate a new gpuArray after gathering to the host."
    },
    {
      "question": "Where can I learn more?",
      "answer": "See the references below and the RunMat source for implementation details."
    }
  ],
  "links": [
    {
      "label": "`islogical`",
      "url": "./islogical"
    },
    {
      "label": "`gpuArray`",
      "url": "./gpuarray"
    },
    {
      "label": "`gather`",
      "url": "./gather"
    },
    {
      "label": "`find`",
      "url": "./find"
    }
  ],
  "source": {
    "label": "crates/runmat-runtime/src/builtins/logical/ops.rs",
    "url": "crates/runmat-runtime/src/builtins/logical/ops.rs"
  },
  "gpu_residency": "You rarely need to call `gpuArray` manually. When the acceleration provider is active, RunMat keeps logical conversions on the GPU by issuing `elem_ne(X, 0)` kernels (backed by `zeros_like` allocations) and flagging the handle as logical metadata. Explicit `gpuArray` calls are available for MATLAB compatibility or when you want to pin residency before interacting with external libraries. When the provider lacks the necessary hook, RunMat documents the fallback: it gathers the data, converts it on the host, and—if a provider is still available—re-uploads the logical mask so downstream GPU code continues to work without residency surprises.",
  "gpu_behavior": [
    "When a GPU provider implements `elem_ne` and `zeros_like`, RunMat performs the conversion in-place on the device by evaluating `elem_ne(X, 0)`, then marks the resulting handle as logical so predicates like `islogical` work without downloads.",
    "If the provider cannot service the request (missing hooks, unsupported dtype, or allocation failure), the value is transparently gathered to the host, converted, and—when a provider is still available—re-uploaded as a logical gpuArray. The fallback is documented so users understand potential host/device transitions.",
    "Handles that are already flagged as logical (`gpuArray.logical`) are returned without modification.",
    "Scalars remain scalars: converting a `gpuArray` scalar preserves the residency and returns a logical gpuArray scalar."
  ]
}