{"record":{"id":"753a85ad317d17eb","repo":"jax-ml/jax","slug":"method-qdwh-only-supports-mxn-matrices-where-m","errorCode":null,"errorMessage":"method='qdwh' only supports mxn matrices where m < n where side='right' and m >= n side='left', got {a.shape} with {side=}","messagePattern":"method='qdwh' only supports mxn matrices where m < n where side='right' and m >= n side='left', got (.+?) with (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/linalg.py","lineNumber":2030,"sourceCode":"  eigenvectors = _compute_eigenvectors(alpha, beta, mid, key)\n  return mid, eigenvectors.T\n\n@jit(static_argnames=('side', 'method'))\n@config.default_matmul_precision(\"float32\")\ndef _polar_2d(a: Array, side: str, method: str, eps: float | None,\n              max_iterations: int | None) -> tuple[Array, Array]:\n  m, n = a.shape\n  if method == \"qdwh\":\n    # TODO(phawkins): return info also if the user opts in?\n    if m >= n and side == \"right\":\n      unitary, posdef, _, _ = qdwh.qdwh(a, is_hermitian=False, eps=eps)\n    elif m < n and side == \"left\":\n      a = a.T.conj()\n      unitary, posdef, _, _ = qdwh.qdwh(a, is_hermitian=False, eps=eps)\n      posdef = posdef.T.conj()\n      unitary = unitary.T.conj()\n    else:\n      raise NotImplementedError(\"method='qdwh' only supports mxn matrices \"\n                                \"where m < n where side='right' and m >= n \"\n                                f\"side='left', got {a.shape} with {side=}\")\n  elif method == \"svd\":\n    u_svd, s_svd, vh_svd = lax_linalg.svd(a, full_matrices=False)\n    s_svd = s_svd.astype(u_svd.dtype)\n    unitary = u_svd @ vh_svd\n    if side == \"right\":\n      posdef = (vh_svd.T.conj() * s_svd[None, :]) @ vh_svd\n    else:\n      posdef = (u_svd * s_svd[None, :]) @ (u_svd.T.conj())\n  else:\n    raise ValueError(f\"Unknown polar decomposition method {method}.\")\n  return unitary, posdef\n\n\n@jit(static_argnames=('side', 'method'))\ndef polar(a: ArrayLike, side: str = 'right', *, method: str = 'qdwh', eps: float | None = None,\n          max_iterations: int | None = None) -> tuple[Array, Array]:","sourceCodeStart":2012,"sourceCodeEnd":2048,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/linalg.py#L2012-L2048","documentation":"The QDWH-based polar decomposition in jax.scipy.linalg.polar only handles matrices where the shape/side combination lets it reduce to the wide m<n case with side='right' (transposing otherwise). If you pass side='right' with m>=n, or side='left' with m<n, the unsupported combination raises NotImplementedError. This is a limitation of the qdwh implementation path, not of polar decomposition in general.","triggerScenarios":"polar(a, side='right', method='qdwh') with a of shape (m, n) where m >= n; or polar(a, side='left', method='qdwh') with m < n.","commonSituations":"Using method='qdwh' (the default) on tall matrices with the default side='right', e.g. in orthogonalization/Procrustes pipelines ported from NumPy where side was never considered.","solutions":["Switch to the SVD path: polar(a, side=..., method='svd') — always supported","Swap the side: use side='left' when m>=n or side='right' when m<n","Transpose the input manually and transpose the results back","Update JAX; newer versions may normalize shapes internally"],"exampleFix":"# before\nU, H = jax.scipy.linalg.polar(a)  # a shape (100, 10) -> raises\n# after\nU, H = jax.scipy.linalg.polar(a, side='left')\n# or\nU, H = jax.scipy.linalg.polar(a, method='svd')","handlingStrategy":"fallback","validationCode":"import jax.numpy as jnp\n\ndef polar_safe(a, side='right', method='qdwh'):\n    a = jnp.asarray(a)\n    m, n = a.shape[-2:]\n    if method == 'qdwh':\n        if side == 'right' and m >= n: side = 'left'\n        elif side == 'left' and m < n: side = 'right'\n    return jax.scipy.linalg.polar(a, side=side, method=method)","typeGuard":null,"tryCatchPattern":"try:\n    U, H = polar(a, side=side)\nexcept NotImplementedError:\n    U, H = polar(a, side=side, method='svd')","preventionTips":["Normalize the side argument from the matrix aspect ratio before calling polar with qdwh","Know the shape/side contract: qdwh handles (m<n, right) and (m>=n, left)","Keep method='svd' as a universal fallback path"],"tags":["jax","polar-decomposition","qdwh","shape-mismatch"],"backgroundTag":"unsupported-shape-combination","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}