runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "and",
  "category": "logical/bit",
  "keywords": [
    "logical and",
    "elementwise and",
    "boolean and",
    "MATLAB and",
    "gpuArray and"
  ],
  "summary": "Element-wise logical AND for scalars, arrays, and gpuArray values.",
  "references": [],
  "gpu_support": {
    "elementwise": true,
    "reduction": false,
    "precisions": [
      "f32",
      "f64"
    ],
    "broadcasting": "matlab",
    "notes": "Runs entirely on the GPU when the active provider implements `logical_and`; otherwise inputs gather back to the host automatically."
  },
  "fusion": {
    "elementwise": true,
    "reduction": false,
    "max_inputs": 2,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::logical::bit::and::tests",
    "integration": "builtins::logical::bit::and::tests::and_gpu_roundtrip",
    "gpu": "builtins::logical::bit::and::tests::and_wgpu_matches_host_path"
  },
  "description": "`and(A, B)` returns the element-wise logical AND of its inputs. Any non-zero value (including `NaN`) evaluates to `true`. The result is a logical scalar when the broadcasted shape has exactly one element, or a logical array otherwise.",
  "behaviors": [
    "Accepts logical, numeric, complex, and character arrays; character code points of zero evaluate to `false`.",
    "Supports MATLAB-style implicit expansion so scalars and singleton dimensions broadcast automatically.",
    "Propagates empty dimensions: if a broadcasted axis has length `0`, the output is an empty logical array with the same shape.",
    "Treats `NaN` values as `true`, matching MATLAB's element-wise logical semantics.",
    "Keeps `gpuArray` inputs on device when the active provider exposes the `logical_and` hook; otherwise the runtime gathers to host transparently."
  ],
  "examples": [
    {
      "description": "Check if two logical scalars are both true",
      "input": "result = and(true, false)",
      "output": "result =\n     0"
    },
    {
      "description": "Combine numeric arrays element-wise with logical AND",
      "input": "A = [1 0 2 0];\nB = [3 4 0 0];\nC = and(A, B)",
      "output": "C =\n  1×4 logical array\n     1     0     0     0"
    },
    {
      "description": "Apply logical AND with automatic scalar expansion",
      "input": "mask = [1; 0; 3; 0];\nflag = and(mask, 5)",
      "output": "flag =\n  4×1 logical array\n     1\n     0\n     1\n     0"
    },
    {
      "description": "Use logical AND with character arrays",
      "input": "lhs = ['R' 'u' 'n'];\nrhs = ['R' 'u' 0];\nmatch = and(lhs, rhs)",
      "output": "match =\n  1×3 logical array\n     1     1     0"
    },
    {
      "description": "Run logical AND directly on the GPU",
      "input": "G1 = gpuArray([0 2 0 4]);\nG2 = gpuArray([1 0 3 4]);\ndeviceResult = and(G1, G2)\nhostResult = gather(deviceResult)",
      "output": "deviceResult =\n  1×4 gpuArray logical array\n     0     0     0     1\nhostResult =\n  1×4 logical array\n     0     0     0     1"
    }
  ],
  "faqs": [
    {
      "question": "Does `and` return logical values?",
      "answer": "Yes. The result is a logical scalar (`true`/`false`) when the broadcasted shape contains exactly one element; otherwise the function returns a logical array. On the GPU the kernel writes `0.0`/`1.0` elements, and the runtime converts them back to logical values when you gather."
    },
    {
      "question": "How are `NaN` values handled?",
      "answer": "`NaN` counts as `true`. For example, `and(NaN, 5)` returns `true` because both operands evaluate to non-zero."
    },
    {
      "question": "Is implicit expansion supported?",
      "answer": "Yes. The inputs follow MATLAB-style implicit expansion rules: dimensions of length `1` broadcast across the other input. Fully incompatible shapes raise a size-mismatch error."
    },
    {
      "question": "Can I use `and` with complex numbers?",
      "answer": "Yes. Real or complex inputs return `true` when either the real or imaginary component is non-zero. For example, `and(1 + 0i, 0 + 2i)` returns `true`."
    },
    {
      "question": "How does `and` differ from the `&` operator?",
      "answer": "They share the same element-wise semantics. The functional form is convenient for higher-order code (for example, `arrayfun(@and, ...)`) and for aligning with MATLAB documentation. Use `&&` or `||` for short-circuit scalar logic."
    },
    {
      "question": "What happens when only one input is a `gpuArray`?",
      "answer": "RunMat promotes the other input to the GPU before dispatch when the auto-offload planner decides it is profitable. If the provider lacks a device implementation, both operands gather to host automatically and the logical result executes on the CPU."
    }
  ],
  "links": [
    {
      "label": "gpuArray",
      "url": "./gpuarray"
    },
    {
      "label": "gather",
      "url": "./gather"
    },
    {
      "label": "not",
      "url": "./not"
    },
    {
      "label": "or",
      "url": "./or"
    },
    {
      "label": "xor",
      "url": "./xor"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/logical/bit/and.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/logical/bit/and.rs"
  },
  "gpu_residency": "You usually do **not** need to call `gpuArray` explicitly. RunMat's native auto-offload logic moves data to the GPU when a fused expression benefits from device execution, and results stay resident until you gather them or the planner needs host access. Call `gpuArray` only when you want to seed residency manually, or when you are porting MATLAB code that already uses explicit device transfers.",
  "gpu_behavior": [
    "When both operands reside on the GPU and the active provider implements the `logical_and` hook, RunMat lowers the call into a device kernel that writes `0` or `1` for each element. The fusion planner treats `and` as an element-wise operation, so fused expressions (for example, `and(A > 0, B)`) stay on device without intermediate gathers. If the provider lacks the hook, the runtime gathers the inputs to host memory automatically and executes the CPU implementation instead of failing."
  ]
}