def var(
        self,
        axis: int | tuple[int, ...] | None = None,
        dtype: np.dtype[Any] | None = None,
        out: ndarray | None = None,
        ddof: int = 0,
        keepdims: bool = False,
        *,
        where: ndarray | None = None,
    ) -> ndarray:
        """a.var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False)

        Returns the variance of the array elements along given axis.

        Refer to :func:`cupynumeric.var` for full documentation.

        See Also
        --------
        cupynumeric.var : equivalent function

        Availability
        --------
        Multiple GPUs, Multiple CPUs

        """
        if axis is not None and not isinstance(axis, int):
            raise NotImplementedError(
                "cupynumeric.var only supports int types for `axis` currently"
            )

        # this could be computed as a single pass through the array
        # by computing both <x^2> and <x> and then computing <x^2> - <x>^2.
        # this would takee the difference of two large numbers and is unstable
        # the mean needs to be computed first and the variance computed
        # directly as <(x-mu)^2>, which then requires two passes through the
        # data to first compute the mean and then compute the variance
        # see https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
        # TODO(https://github.com/nv-legate/cupynumeric/issues/590)

        dtype = self._summation_dtype(dtype)
        # calculate the mean, but keep the dimensions so that the
        # mean can be broadcast against the original array
        mu = self.mean(axis=axis, dtype=dtype, keepdims=True, where=where)

        where_array = broadcast_where(where, self.shape)

        # 1D arrays (or equivalent) should benefit from this unary reduction:
        if axis is None or calculate_volume(tuple_pop(self.shape, axis)) == 1:
            # this is a scalar reduction and we can optimize this as a single
            # pass through a scalar reduction
            result = perform_unary_reduction(
                UnaryRedCode.VARIANCE,
                self,
                axis=axis,
                dtype=dtype,
                out=out,
                keepdims=keepdims,
                where=where_array,
                # FIXME(wonchanl): the following code blocks on mu to convert
                # it to a Scalar object. We need to get rid of this blocking by
                # allowing the extra arguments to be Legate stores
                args=(Scalar(mu.__array__(), to_core_type(self.dtype)),),
            )
        else:
            # TODO(https://github.com/nv-legate/cupynumeric/issues/591)
            # there isn't really support for generic binary reductions
            # right now all of the current binary reductions are boolean
            # reductions like allclose. To implement this a single pass would
            # require a variant of einsum/dot that produces
            # (self-mu)*(self-mu) rather than self*mu. For now, we have to
            # compute delta = self-mu in a first pass and then compute
            # delta*delta in second pass
            delta = self - mu

            result = perform_unary_reduction(
                UnaryRedCode.SUM_SQUARES,
                delta,
                axis=axis,
                dtype=dtype,
                out=out,
                keepdims=keepdims,
                where=where_array,
            )

        self._normalize_summation(
            result,
            axis=axis,
            ddof=ddof,
            keepdims=keepdims,
            where=where_array,
        )

        return result
a.var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False)

        Returns the variance of the array elements along given axis.

        Refer to :func:`cupynumeric.var` for full documentation.

        See Also
        --------
        cupynumeric.var : equivalent function

        Availability
        --------
        Multiple GPUs, Multiple CPUs

        
cupynumeric/_array/array.py