UNIFORM_DIRECTION

Overview

The UNIFORM_DIRECTION function generates random unit vectors (directions) that are uniformly distributed on the surface of a hypersphere in n-dimensional space. This is essential for applications in Monte Carlo simulations, directional statistics, computer graphics, and machine learning where unbiased sampling of directions is required.

This implementation uses the SciPy library’s uniform_direction distribution, which is part of the scipy.stats module. The underlying algorithm is based on Marsaglia’s method (1972), a well-established technique for generating uniformly distributed points on the surface of an n-sphere.

Marsaglia’s algorithm works by generating n independent standard normal random variables x_1, x_2, \ldots, x_n and then normalizing the resulting vector to unit length. The normalized vector is computed as:

\mathbf{u} = \frac{\mathbf{x}}{\|\mathbf{x}\|} = \frac{(x_1, x_2, \ldots, x_n)}{\sqrt{x_1^2 + x_2^2 + \cdots + x_n^2}}

This method leverages the spherical symmetry of the multivariate normal distribution. Since the joint distribution of independent standard normal variables is rotationally invariant, the projection onto the unit sphere yields a uniform distribution over the hypersphere’s surface.

In geometric terms, for dim=2, the function samples points uniformly from a unit circle (S^1). For dim=3, it samples from the surface of a unit sphere (S^2), which can be interpreted as random 3D directions. Higher dimensions generalize to hyperspheres S^{n-1} embedded in n-dimensional Euclidean space. Each output vector has Euclidean norm equal to 1.

For the original algorithm, see: Marsaglia, G. (1972). “Choosing a Point from the Surface of a Sphere”. Annals of Mathematical Statistics, 43(2): 645–646. doi:10.1214/aoms/1177692644.

This example function is provided as-is without any representation of accuracy.

Excel Usage

=UNIFORM_DIRECTION(dim, size)
  • dim (int, required): Number of dimensions for the unit vectors. Must be >= 2.
  • size (int, optional, default: 1): Number of samples to generate. Must be >= 1.

Returns (list[list]): 2D list of unit vectors, or error message string.

Examples

Example 1: Single 2D unit vector

Inputs:

dim
2

Excel formula:

=UNIFORM_DIRECTION(2)

Expected output:

"non-error"

Example 2: Single 3D unit vector

Inputs:

dim
3

Excel formula:

=UNIFORM_DIRECTION(3)

Expected output:

"non-error"

Example 3: Multiple 2D unit vectors

Inputs:

dim size
2 4

Excel formula:

=UNIFORM_DIRECTION(2, 4)

Expected output:

"non-error"

Example 4: Multiple 5D unit vectors

Inputs:

dim size
5 2

Excel formula:

=UNIFORM_DIRECTION(5, 2)

Expected output:

"non-error"

Python Code

from scipy.stats import uniform_direction as scipy_uniform_direction
import numpy as np

def uniform_direction(dim, size=1):
    """
    Draws random unit vectors uniformly distributed on the surface of a hypersphere in the specified dimension.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.uniform_direction.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        dim (int): Number of dimensions for the unit vectors. Must be >= 2.
        size (int, optional): Number of samples to generate. Must be >= 1. Default is 1.

    Returns:
        list[list]: 2D list of unit vectors, or error message string.
    """
    def is_int(x):
        if isinstance(x, bool):
            return False
        if isinstance(x, int):
            return True
        if isinstance(x, float):
            return x.is_integer()
        return False

    # Validate dim
    if not is_int(dim) or int(dim) < 2:
        return "Invalid input: dim must be an integer >= 2."
    dim = int(dim)
    # Validate size
    if size is None:
        size = 1
    if not is_int(size) or int(size) < 1:
        return "Invalid input: size must be an integer >= 1."
    size = int(size)
    try:
        # Draw random unit vectors
        result = scipy_uniform_direction.rvs(dim=dim, size=size)
    except Exception as e:
        return f"scipy.stats.uniform_direction error: {e}"
    # Always return a 2D list of floats
    arr = np.array(result)
    if arr.ndim == 1:
        # Single sample: shape (dim,)
        return [arr.astype(float).tolist()]
    elif arr.ndim == 2:
        # Multiple samples: shape (size, dim)
        return arr.astype(float).tolist()
    else:
        return "Unexpected output shape from scipy.stats.uniform_direction."

Online Calculator