Numeric Typing

Buffalo Wings uses a small set of shared numeric type aliases to keep NumPy-heavy APIs consistent and readable. These aliases are part of the public API and are exposed from buffalo_wings.type_aliases.

Core Aliases

Use buffalo_wings.type_aliases.FloatScalar for parameters or return values that must be a single floating-point value.

Use buffalo_wings.type_aliases.FloatArray for parameters or return values that must be NumPy arrays with float64 dtype.

Use buffalo_wings.type_aliases.FloatInput for input parameters that may be:

  • a Python float,

  • a NumPy floating scalar,

  • a sequence of floating values,

  • or a NumPy floating array.

Main Rules

Use FloatInput only for input parameters. Do not use FloatInput for return types.

When a function accepts FloatInput, normalize it immediately at the function boundary with np.asarray(value, dtype=np.float64).

Prefer returning FloatArray from vectorized APIs even when scalar inputs are accepted for convenience.

In runtime geometry code under buffalo_wings.airfoil and buffalo_wings.wing, prefer FloatScalar for scalar numeric parameters, return values, and cached state when NumPy scalar values are valid.

In schema dataclasses and other serialized user-facing structures, prefer plain built-in scalar types such as float, int, str, and bool.

Keep plain float at third-party boundaries that require a Python float, such as SciPy callback signatures and similar scalar-only interfaces.

Why This Convention Exists

This convention keeps public signatures readable while still allowing scalar convenience at call sites. It also makes it easier to distinguish between scalar-only values, normalized NumPy arrays, and flexible numeric inputs.

Example

The following pattern is preferred for geometry methods:

import numpy as np
import buffalo_wings.type_aliases as bw_type


def sample_curve(t: bw_type.FloatInput) -> bw_type.FloatArray:
    t_array = np.asarray(t, dtype=np.float64)
    ...


def chord_length() -> bw_type.FloatScalar:
    ...

Scalar-only parameters should use FloatScalar directly rather than FloatInput.