Functional Weave
Code in Rust

math.pow@1.0.0

impl/python.py

1,876 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import math

from .math_exp import exp  ← from math.exp ^1.0.0 · built alongside by fune
from .math_ln import ln  ← from math.ln ^1.0.0 · built alongside by fune

# Below this exponent of e the result is smaller than any normal double.
_SMALLEST = -708
_LARGEST = 709


def pow(base: float, exponent: float) -> float:  # noqa: A001 - the manifest names it pow
    """base^exponent with the same bits in TypeScript, Python and Rust.

    A whole-number exponent is done by repeated squaring, so 10^3 is exactly
    1000; any other is exp(exponent * ln(base)) from math.exp and math.ln.
    Python's ** and math.pow use the C library, whose last bit may differ.
    """
    for v, what in ((base, "base"), (exponent, "exponent")):
        if isinstance(v, bool) or not isinstance(v, (int, float)) or not math.isfinite(v):
            raise ValueError("pow needs a finite %s, received %r" % (what, v))
    base = float(base)
    exponent = float(exponent)
    if base == 0:
        if exponent < 0:
            raise ValueError("zero cannot be raised to a negative power")
        return 1.0 if exponent == 0 else 0.0
    if math.floor(exponent) == exponent:
        n = int(abs(exponent))
        b = base
        result = 1.0
        while n > 0:
            if n % 2 == 1:
                result *= b
            n //= 2
            if n > 0:
                b *= b
        if exponent < 0:
            if result == 0 or math.isinf(result):
                result = 0.0 if math.isinf(result) else math.inf
            else:
                result = 1 / result
        if not math.isfinite(result):
            raise ValueError("pow result is too large to represent")
        return result + 0.0
    if base < 0:
        raise ValueError("a negative base needs a whole-number exponent")
    power = exponent * ln(base)
    if power > _LARGEST:
        raise ValueError("pow result is too large to represent")
    if power < _SMALLEST:
        return 0.0
    return exp(power)