code: def _complex_mul(mul, x, y):
      # We use a trick for complex multiplication sometimes attributed to Gauss
      # which uses three multiplications and five additions; instead of the naive
      # method of four multiplications and two additions.
      # https://en.wikipedia.org/wiki/Multiplication_algorithm#Complex_multiplication_algorithm
      #
      # This performance win comes with a trade-off in accuracy; especially in
      # cases when the real and imaginary differ hugely in magnitude. The relative
      # error bound (e.g. 1p-24 in case of float32) would be relative to the
      # maximum of real and imaginary parts of the result instead of being
      # satisfied by the real and imaginary parts independently of each other.
      x_re, x_im = lax.real(x), lax.imag(x)
      y_re, y_im = lax.real(y), lax.imag(y)
      k1 = mul(lax.add(x_re, x_im), y_re)
      k2 = mul(x_re, lax.sub(y_im, y_re))
      k3 = mul(x_im, lax.add(y_re, y_im))
      return lax.complex(lax.sub(k1, k3), lax.add(k1, k2))
  
imports: from __future__ import annotations
  from collections.abc import Sequence
  from functools import partial
  import operator
  from typing import NamedTuple, Union
  import numpy
  from jax._src import core
  from jax._src import dtypes
  from jax._src import util
  from jax._src.interpreters import ad
  from jax._src.interpreters import batching
  from jax._src.interpreters import mlir
  from jax._src.lax import lax
  from jax._src.lib.mlir.dialects import hlo
  from jax._src.typing import Array, DTypeLike
label_desc: Use image node_id 12 for calling a global function with example usage: _complex_mul(mul, x, y) and returns: lax