runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "asin",
  "category": "math/trigonometry",
  "keywords": [
    "asin",
    "inverse sine",
    "arcsin",
    "trigonometry",
    "gpu"
  ],
  "summary": "Element-wise inverse sine with full MATLAB-compatible complex promotion and GPU fallbacks.",
  "references": [],
  "gpu_support": {
    "elementwise": true,
    "reduction": false,
    "precisions": [
      "f32",
      "f64"
    ],
    "broadcasting": "matlab",
    "notes": "Uses the provider's unary_asin hook when all elements stay within [-1, 1]; gathers to host otherwise."
  },
  "fusion": {
    "elementwise": true,
    "reduction": false,
    "max_inputs": 1,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::math::trigonometry::asin::tests",
    "integration": "builtins::math::trigonometry::asin::tests::asin_gpu_provider_roundtrip"
  },
  "description": "`Y = asin(X)` computes the inverse sine (in radians) of every element of `X`. Results follow MATLAB semantics for real, logical, character, and complex inputs. Real values outside the `[-1, 1]` interval transparently promote to complex outputs so that the mathematical definition remains exact.",
  "behaviors": [
    "Accepts scalars, vectors, matrices, and N-D tensors and applies the operation element-wise with MATLAB broadcasting rules.",
    "Logical inputs convert to doubles (`true → 1.0`, `false → 0.0`) before the inverse sine is taken.",
    "Character arrays are interpreted as their numeric code points and return dense double or complex tensors, depending on the result.",
    "Real inputs with magnitude greater than `1` produce complex results identical to MATLAB (`asin(1.2) → 1.5708 - 0.6224i`).",
    "Complex inputs follow MATLAB's principal branch definitions using `asin(z) = -i log(iz + sqrt(1 - z^2))`.",
    "NaNs and infinities propagate according to IEEE arithmetic and match MATLAB's edge cases."
  ],
  "examples": [
    {
      "description": "Inverse sine of a scalar angle",
      "input": "y = asin(0.5)",
      "output": "y = 0.5236"
    },
    {
      "description": "Inverse sine of values greater than one (complex output)",
      "input": "z = asin(1.2)",
      "output": "z = 1.5708 - 0.6224i"
    },
    {
      "description": "Compute arcsine of every element in a matrix",
      "input": "A = [0 -0.5 0.75; 1 0.25 -0.8];\nY = asin(A)",
      "output": "Y =\n    0          -0.5236    0.8481\n    1.5708      0.2527   -0.9273"
    },
    {
      "description": "Handling logical input with automatic double promotion",
      "input": "mask = logical([0 1 1 0]);\nangles = asin(mask)",
      "output": "angles = [0 1.5708 1.5708 0]"
    },
    {
      "description": "Computing `asin` on a GPU array and keeping the result on device",
      "input": "G = gpuArray(linspace(-1, 1, 5));\nresult_gpu = asin(G);\nresult = gather(result_gpu)",
      "output": "result = [-1.5708 -0.5236 0 0.5236 1.5708]"
    },
    {
      "description": "Evaluating inverse sine of complex numbers",
      "input": "vals = [1+2i, -0.5+0.75i];\nw = asin(vals)",
      "output": "w =\n   0.4271 + 1.5286i\n  -0.3983 + 0.7433i"
    }
  ],
  "faqs": [
    {
      "question": "Why does `asin` sometimes return complex numbers?",
      "answer": "MATLAB (and RunMat) define inverse sine on the complex plane. Real inputs with magnitude greater than `1` lie outside the real domain, so the correct answer is complex. RunMat matches MATLAB's principal branch, yielding identical results."
    },
    {
      "question": "Does `asin` support GPU execution?",
      "answer": "Yes. When a provider implements `unary_asin` and exposes reduction hooks for bounds checking, the runtime executes `asin` entirely on the device. If complex promotion is required, RunMat gathers to the host to stay mathematically correct."
    },
    {
      "question": "How does `asin` treat logical or integer inputs?",
      "answer": "Logical arrays convert to doubles (`0` or `1`). Integers convert to double precision before evaluation, mirroring MATLAB and avoiding overflow. The final result is double or complex depending on the data."
    },
    {
      "question": "What happens with NaN or Inf values?",
      "answer": "NaNs propagate through the computation. Inputs of `±Inf` produce complex infinities consistent with MATLAB's handling of special values."
    },
    {
      "question": "Can I keep the result on the GPU if it becomes complex?",
      "answer": "Complex results are currently returned on the host because GPU tensor handles represent real data. The runtime gathers automatically and returns `Value::Complex`/`Value::ComplexTensor`, guaranteeing correct MATLAB semantics."
    },
    {
      "question": "Why does `asin` of a character array return numeric arrays?",
      "answer": "Character arrays are interpreted as their Unicode code points, converted to doubles, and then the inverse sine is applied. Any element outside `[-1, 1]` may promote the whole array to complex— matching MATLAB behaviour."
    },
    {
      "question": "Does `asin` fuse with surrounding element-wise operations?",
      "answer": "Yes. The fusion planner can emit fused WGSL kernels that include `asin` as long as the provider supports the generated code path. When fused, `asin` participates in GPU auto-offload decisions like other unary operations."
    },
    {
      "question": "Are there precision differences between CPU and GPU paths?",
      "answer": "Both CPU and GPU implementations operate in the provider's precision (`f32` or `f64`). Results match within normal floating-point error tolerances. For values near the domain boundary `±1`, minor rounding differences may appear but stay within MATLAB compatibility requirements."
    }
  ],
  "links": [
    {
      "label": "sin",
      "url": "./sin"
    },
    {
      "label": "acos",
      "url": "./acos"
    },
    {
      "label": "atan",
      "url": "./atan"
    },
    {
      "label": "gpuArray",
      "url": "./gpuarray"
    },
    {
      "label": "gather",
      "url": "./gather"
    },
    {
      "label": "acosh",
      "url": "./acosh"
    },
    {
      "label": "asinh",
      "url": "./asinh"
    },
    {
      "label": "atan2",
      "url": "./atan2"
    },
    {
      "label": "atanh",
      "url": "./atanh"
    },
    {
      "label": "cos",
      "url": "./cos"
    },
    {
      "label": "cosh",
      "url": "./cosh"
    },
    {
      "label": "sinh",
      "url": "./sinh"
    },
    {
      "label": "tan",
      "url": "./tan"
    },
    {
      "label": "tanh",
      "url": "./tanh"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/math/trigonometry/asin.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/math/trigonometry/asin.rs"
  },
  "gpu_residency": "You usually do **not** need to call `gpuArray` explicitly. The fusion planner keeps tensors on the GPU whenever the active provider exposes the `unary_asin` hook and the inputs remain within `[-1, 1]`. When complex promotion is required, RunMat gathers the data and returns the correct complex result automatically. Manual `gpuArray` / `gather` calls remain available for workflows that need explicit residency control.",
  "gpu_behavior": [
    "RunMat Accelerate keeps tensors on the GPU when:\n\n1. A provider is registered and implements `unary_asin`, `reduce_min`, and `reduce_max`. 2. The runtime can prove that every element lies within the real domain `[-1, 1]`.\n\nIf any of those hooks are missing, or if the bounds check cannot run (for example, because the provider does not support the min/max reductions for the current tensor layout), RunMat falls back to the host implementation automatically so the results remain correct.\n\nWhen either condition fails—most notably when the input requires complex promotion—the runtime gathers the data to the host, computes the MATLAB-compatible result, and returns a host-resident (or complex) value. This mirrors MATLAB's behaviour without forcing users to manually call `gpuArray` or `gather`."
  ]
}