Source code for torchoutil.pyoutil.math

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import math
import struct
from numbers import Real
from typing import Optional, TypeVar

from .functools import function_alias

T = TypeVar("T", bound=Real)


[docs]def clip(x: T, xmin: Optional[T] = None, xmax: Optional[T] = None) -> T: if xmin is not None: x = max(x, xmin) if xmax is not None: x = min(x, xmax) return x
[docs]@function_alias(clip) def clamp(*args, **kwargs): ...
[docs]def nextdown(x: float) -> float: return -_nextup(-x)
[docs]def nextafter(x: float, y: float) -> float: """Equivalent to `math.nextafter` for python <=3.8.""" # BASED on https://stackoverflow.com/questions/10420848/how-do-you-get-the-next-value-in-the-floating-point-sequence/10426033#10426033 # If either argument is a NaN, return that argument. # This matches the implementation in decimal.Decimal if math.isnan(x): return x if math.isnan(y): return y if y == x: return y elif y > x: return _nextup(x) else: return nextdown(x)
def _nextup(x: float) -> float: # NaNs and positive infinity map to themselves. if math.isnan(x) or (math.isinf(x) and x > 0): return x # 0.0 and -0.0 both map to the smallest +ve float. if x == 0.0: x = 0.0 n = struct.unpack("<q", struct.pack("<d", x))[0] if n >= 0: n += 1 else: n -= 1 return struct.unpack("<d", struct.pack("<q", n))[0]