runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "squeeze",
  "category": "array/shape",
  "keywords": [
    "squeeze",
    "singleton dimensions",
    "array reshape",
    "gpu"
  ],
  "summary": "Remove singleton (size-one) dimensions while preserving MATLAB vector semantics.",
  "references": [],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [
      "f32",
      "f64",
      "i32",
      "bool"
    ],
    "broadcasting": "none",
    "notes": "Backends reuse the reshape hook to update device metadata; runtimes fall back to host metadata updates when unavailable."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 1,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::array::shape::squeeze::tests",
    "integration": "builtins::array::shape::squeeze::tests::squeeze_gpu_roundtrip"
  },
  "description": "`squeeze(A)` removes singleton (dimension size equal to one) dimensions from `A`. The result keeps MATLAB's row/column vector semantics—2-D matrices stay 2-D, and higher-rank arrays collapse down until only meaningful axes remain.",
  "behaviors": [
    "Dimensions greater than two drop all size-one axes. If exactly one dimension remains, the output becomes an `N × 1` column vector.",
    "Two-dimensional inputs (row/column vectors and matrices) are returned unchanged.",
    "Zero-length dimensions are preserved; only length-one axes are removed.",
    "Scalar values remain scalars.",
    "GPU arrays stay resident on the device where possible; the runtime only gathers when it cannot infer the shape."
  ],
  "examples": [
    {
      "description": "Removing Singleton Dimensions from a 3-D Matrix",
      "input": "A = reshape(1:12, [1, 3, 4]);\nB = squeeze(A);\nsize(B)",
      "output": "ans = [3 4]"
    },
    {
      "description": "Turning 1x1xN Slices into Column Vectors",
      "input": "T = zeros(1, 1, 5);\nT(:, :, 3) = 7;\nvec = squeeze(T);\nsize(vec)",
      "output": "ans = [5 1]"
    },
    {
      "description": "Keeping Row Vectors Unchanged After Squeeze",
      "input": "row = rand(1, 8);\nout = squeeze(row);\nsize(out)",
      "output": "ans = [1 8]"
    },
    {
      "description": "Squeezing Logical Masks from Simulations",
      "input": "mask = false(1, 10, 1, 1);\nmask(1, 4, 1, 1) = true;\nflat = squeeze(mask)",
      "output": "flat = [0 0 0 1 0 0 0 0 0 0]'"
    },
    {
      "description": "Using Squeeze on GPU-Resident Data",
      "input": "G = gpuArray(rand(1, 64, 1));\nH = squeeze(G);\nisgpuarray(H)",
      "output": "ans = logical 1"
    },
    {
      "description": "Squeezing String Arrays While Preserving Layout",
      "input": "S = strings(1, 1, 3);\nS(1, 1, 1) = \"run\";\nS(1, 1, 2) = \"mat\";\nS(1, 1, 3) = \"gpu\";\nT = squeeze(S);\nsize(T)",
      "output": "ans = [3 1]"
    }
  ],
  "faqs": [
    {
      "question": "Why does `squeeze` keep 2-D matrices unchanged?",
      "answer": "MATLAB treats row and column vectors as 2-D objects. Preserving those dimensions avoids turning row vectors into column vectors or scalars unintentionally."
    },
    {
      "question": "What happens when every dimension is singleton?",
      "answer": "The result becomes a `1 × 1` array. Scalars (e.g., plain doubles) remain scalars."
    },
    {
      "question": "Does `squeeze` affect zero-length dimensions?",
      "answer": "No. Only size-one dimensions are removed. Zero-length dimensions are preserved exactly."
    },
    {
      "question": "Can I `squeeze` character or cell arrays?",
      "answer": "Yes. They already store up to two dimensions in RunMat, so `squeeze` leaves them unchanged but still validates inputs."
    },
    {
      "question": "How does `squeeze` interact with GPU tensors?",
      "answer": "The runtime updates GPU tensor metadata via the provider's reshape hook. Data stays on the device unless a provider cannot report shape information, in which case RunMat gathers once to infer dimensions."
    },
    {
      "question": "What if I need to remove a specific dimension?",
      "answer": "Use `reshape`, `permute`, or indexing to reorganize axes manually before calling `squeeze`."
    },
    {
      "question": "Does `squeeze` change data ordering?",
      "answer": "No. It only alters metadata. Element order in memory remains unchanged."
    },
    {
      "question": "Will `squeeze` ever increase the number of dimensions?",
      "answer": "No. It either returns the same number or fewer. The only exception is padding with a trailing singleton to maintain MATLAB's column-vector convention when exactly one dimension remains."
    },
    {
      "question": "Is `squeeze` safe to run before GPU fusion?",
      "answer": "Yes. Since it only updates shapes, it integrates cleanly with fusion and does not impede kernel generation."
    },
    {
      "question": "How do I undo a squeeze?",
      "answer": "Use `reshape` with the original size vector (for example, captured via `size(A)`) to restore the previous dimension layout."
    }
  ],
  "links": [
    {
      "label": "`reshape`",
      "url": "./reshape"
    },
    {
      "label": "`permute`",
      "url": "./permute"
    },
    {
      "label": "`ndims`",
      "url": "./ndims"
    },
    {
      "label": "`size`",
      "url": "./size"
    },
    {
      "label": "`gpuArray`",
      "url": "./gpuarray"
    },
    {
      "label": "`gather`",
      "url": "./gather"
    },
    {
      "label": "cat",
      "url": "./cat"
    },
    {
      "label": "circshift",
      "url": "./circshift"
    },
    {
      "label": "diag",
      "url": "./diag"
    },
    {
      "label": "flip",
      "url": "./flip"
    },
    {
      "label": "fliplr",
      "url": "./fliplr"
    },
    {
      "label": "flipud",
      "url": "./flipud"
    },
    {
      "label": "horzcat",
      "url": "./horzcat"
    },
    {
      "label": "ipermute",
      "url": "./ipermute"
    },
    {
      "label": "kron",
      "url": "./kron"
    },
    {
      "label": "repmat",
      "url": "./repmat"
    },
    {
      "label": "rot90",
      "url": "./rot90"
    },
    {
      "label": "tril",
      "url": "./tril"
    },
    {
      "label": "triu",
      "url": "./triu"
    },
    {
      "label": "vertcat",
      "url": "./vertcat"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/array/shape/squeeze.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/array/shape/squeeze.rs"
  },
  "gpu_behavior": [
    "When a GPU provider is active, RunMat calls the provider's `reshape` hook to update tensor metadata without copying data. Providers that do not override `reshape` fall back to the in-process behaviour, simply updating the handle shape locally. If a handle advertises no shape, RunMat downloads metadata once to infer dimensions before applying `squeeze`."
  ]
}