runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "logspace",
  "category": "array/creation",
  "keywords": [
    "logspace",
    "logarithmic",
    "vector",
    "decade",
    "gpu",
    "frequency"
  ],
  "summary": "Generate logarithmically spaced row vectors that mirror MATLAB behavior.",
  "references": [],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [
      "f32",
      "f64"
    ],
    "broadcasting": "none",
    "notes": "Providers can compose `logspace` from `linspace`, scalar multiplication, and `unary_exp`. When hooks are missing, RunMat generates the sequence on the host and uploads it once to preserve residency."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 0,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::array::creation::logspace::tests",
    "integration": "builtins::array::creation::logspace::tests::logspace_gpu_roundtrip",
    "wgpu": "builtins::array::creation::logspace::tests::logspace_wgpu_matches_cpu"
  },
  "description": "`logspace(a, b, n)` returns `n` points that are equally spaced on a logarithmic scale between `10^a` and `10^b`. When `n` is omitted, MATLAB (and RunMat) default to 50 points. The result is always a `1 × n` row vector.",
  "behaviors": [
    "`logspace(a, b)` is equivalent to `logspace(a, b, 50)`.",
    "`logspace(a, b, 0)` returns a `1 × 0` empty double row vector.",
    "`logspace(a, b, 1)` returns `10^b`.",
    "`logspace(a, b, 2)` returns `[10^a 10^b]`.",
    "Endpoints may be real or complex scalars. Complex inputs produce complex outputs using the analytic definition `10^z = e^{z ln 10}`.",
    "Scalar inputs may be numeric literals, `1×1` tensors, or gathered GPU scalars (`gpuArray` handles). Non-scalar inputs raise an error.",
    "The third argument must be a finite, non-negative integer."
  ],
  "examples": [
    {
      "description": "Creating decades between 10 and 1000",
      "input": "x = logspace(1, 3, 3)",
      "output": "x = [10 100 1000]"
    },
    {
      "description": "Generating logarithmic spacing with the default 50 points",
      "input": "f = logspace(1, 4)",
      "output": "% f is a 1x50 row vector spanning [10, 10^4]\ndisp(f(1));\ndisp(f(end))"
    },
    {
      "description": "Requesting a single logarithmic sample",
      "input": "edge = logspace(-3, 2, 1)",
      "output": "edge = 100"
    },
    {
      "description": "Building a swept frequency vector on the GPU",
      "input": "lo = gpuArray(0);\nhi = gpuArray(3);\nfreq = logspace(lo, hi, 256);\nresp = sin(2*pi*freq)",
      "output": "% freq and resp remain on the GPU when an acceleration provider is active.\ndisp(gather(freq(1:5)))"
    },
    {
      "description": "Producing complex logarithmic spacing",
      "input": "z = logspace(1+1i, 2+2i, 4)",
      "output": "% Complex row vector with magnitudes and phases progressing logarithmically\ndisp(z)"
    },
    {
      "description": "Matching MATLAB's legacy `logspace(a, pi, n)` syntax",
      "input": "theta = logspace(-1, pi, 5)",
      "output": "% Interprets pi literally: theta(end) == 10^pi\ndisp(theta(end))"
    }
  ],
  "faqs": [
    {
      "question": "What base does `logspace` use?",
      "answer": "RunMat follows MATLAB and always computes powers of ten. To use another base, build your own sequence (`base .^ linspace(...)`) or multiply the output by a constant factor."
    },
    {
      "question": "Does `logspace` include both endpoints?",
      "answer": "Yes. The first element is exactly `10^a` and the final element is exactly `10^b`, even when rounding errors could otherwise accumulate."
    },
    {
      "question": "Can I request zero points?",
      "answer": "Yes. `logspace(a, b, 0)` returns a `1 × 0` empty row vector."
    },
    {
      "question": "What happens when `a` equals `b`?",
      "answer": "Every element equals `10^a`. For example, `logspace(2, 2, 4)` returns `[100 100 100 100]`."
    },
    {
      "question": "Does `logspace` support complex endpoints?",
      "answer": "Yes. Real and imaginary components are interpolated independently, and the final values are computed using `10^z = e^{z ln 10}`."
    },
    {
      "question": "Is the third argument required to be an integer?",
      "answer": "Yes. Non-integer or negative counts raise an error, matching MATLAB semantics."
    },
    {
      "question": "Does the function support GPU scalars?",
      "answer": "Yes. GPU scalars are gathered once to determine the sequence, and the resulting vector is uploaded back to the device when profitable."
    },
    {
      "question": "How accurate is the last element?",
      "answer": "The implementation explicitly overwrites the final element with `10^b` to match MATLAB’s behavior and avoid floating-point drift."
    },
    {
      "question": "How does `logspace` differ from `linspace`?",
      "answer": "`linspace` spaces points linearly between two values, whereas `logspace` spaces points logarithmically between powers of ten."
    },
    {
      "question": "Can I generate descending values?",
      "answer": "Yes. `logspace(3, 1, 4)` returns `[1000 464.1589 215.4435 100]`, decreasing logarithmically."
    }
  ],
  "links": [
    {
      "label": "linspace",
      "url": "./linspace"
    },
    {
      "label": "zeros",
      "url": "./zeros"
    },
    {
      "label": "ones",
      "url": "./ones"
    },
    {
      "label": "gpuArray",
      "url": "./gpuarray"
    },
    {
      "label": "gather",
      "url": "./gather"
    },
    {
      "label": "colon",
      "url": "./colon"
    },
    {
      "label": "eye",
      "url": "./eye"
    },
    {
      "label": "false",
      "url": "./false"
    },
    {
      "label": "fill",
      "url": "./fill"
    },
    {
      "label": "magic",
      "url": "./magic"
    },
    {
      "label": "meshgrid",
      "url": "./meshgrid"
    },
    {
      "label": "rand",
      "url": "./rand"
    },
    {
      "label": "randi",
      "url": "./randi"
    },
    {
      "label": "randn",
      "url": "./randn"
    },
    {
      "label": "randperm",
      "url": "./randperm"
    },
    {
      "label": "range",
      "url": "./range"
    },
    {
      "label": "true",
      "url": "./true"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/array/creation/logspace.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/array/creation/logspace.rs"
  },
  "gpu_residency": "You usually do **not** need to call `gpuArray` yourself in RunMat. When an acceleration provider is active and either endpoint already lives on the GPU, RunMat keeps the generated sequence on the device whenever the provider exposes the necessary hooks. If the hooks are missing, RunMat generates the vector on the host and uploads it once. This strategy preserves residency for subsequent kernels while avoiding partial GPU execution.",
  "gpu_behavior": [
    "When either endpoint already resides on the GPU, RunMat attempts to keep the sequence on the device. Providers that implement `linspace`, scalar multiplication, and `unary_exp` can build the vector entirely in device memory. If any hook is unavailable, RunMat generates the sequence on the host and performs a single upload, ensuring downstream kernels still receive a GPU tensor without surprising performance cliffs."
  ]
}