mirror of https://github.com/exaloop/codon.git
1301 lines
28 KiB
Python
1301 lines
28 KiB
Python
# Copyright (C) 2022-2025 Exaloop Inc. <https://exaloop.io>
|
|
|
|
@pure
|
|
@llvm
|
|
def _inf() -> float:
|
|
ret double 0x7FF0000000000000
|
|
|
|
@pure
|
|
@llvm
|
|
def _nan() -> float:
|
|
ret double 0x7FF8000000000000
|
|
|
|
e = 2.7182818284590452354
|
|
pi = 3.14159265358979323846
|
|
tau = 6.28318530717958647693
|
|
inf = _inf()
|
|
nan = _nan()
|
|
|
|
def factorial(x: int) -> int:
|
|
_F = (
|
|
1,
|
|
1,
|
|
2,
|
|
6,
|
|
24,
|
|
120,
|
|
720,
|
|
5040,
|
|
40320,
|
|
362880,
|
|
3628800,
|
|
39916800,
|
|
479001600,
|
|
6227020800,
|
|
87178291200,
|
|
1307674368000,
|
|
20922789888000,
|
|
355687428096000,
|
|
6402373705728000,
|
|
121645100408832000,
|
|
2432902008176640000,
|
|
)
|
|
if not (0 <= x <= 20):
|
|
raise ValueError("factorial is only supported for 0 <= x <= 20")
|
|
return _F[x]
|
|
|
|
def isnan(x: float) -> bool:
|
|
"""
|
|
isnan(float) -> bool
|
|
|
|
Return True if float arg is a NaN, else False.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> bool:
|
|
%y = fcmp uno double %x, 0.000000e+00
|
|
%z = zext i1 %y to i8
|
|
ret i8 %z
|
|
|
|
return f(x)
|
|
|
|
def isinf(x: float) -> bool:
|
|
"""
|
|
isinf(float) -> bool:
|
|
|
|
Return True if float arg is an INF, else False.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> bool:
|
|
declare double @llvm.fabs.f64(double)
|
|
%a = call double @llvm.fabs.f64(double %x)
|
|
%b = fcmp oeq double %a, 0x7FF0000000000000
|
|
%c = zext i1 %b to i8
|
|
ret i8 %c
|
|
|
|
return f(x)
|
|
|
|
def isfinite(x: float) -> bool:
|
|
"""
|
|
isfinite(float) -> bool
|
|
|
|
Return True if x is neither an infinity nor a NaN,
|
|
and False otherwise.
|
|
"""
|
|
return not (isnan(x) or isinf(x))
|
|
|
|
def _check1(arg: float, r: float, can_overflow: bool = False):
|
|
if __py_numerics__:
|
|
if isnan(r) and not isnan(arg):
|
|
raise ValueError("math domain error")
|
|
|
|
if isinf(r) and isfinite(arg):
|
|
if can_overflow:
|
|
raise OverflowError("math range error")
|
|
else:
|
|
raise ValueError("math domain error")
|
|
|
|
return r
|
|
|
|
def _check2(x: float, y: float, r: float, can_overflow: bool = False):
|
|
if __py_numerics__:
|
|
if isnan(r) and not isnan(x) and not isnan(y):
|
|
raise ValueError("math domain error")
|
|
|
|
if isinf(r) and isfinite(x) and isfinite(y):
|
|
if can_overflow:
|
|
raise OverflowError("math range error")
|
|
else:
|
|
raise ValueError("math domain error")
|
|
|
|
return r
|
|
|
|
def ceil(x: float) -> int:
|
|
"""
|
|
ceil(float) -> int
|
|
|
|
Return the ceiling of x as an Integral.
|
|
This is the smallest integer >= x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.ceil.f64(double)
|
|
%y = call double @llvm.ceil.f64(double %x)
|
|
ret double %y
|
|
|
|
return int(f(x))
|
|
|
|
def floor(x: float) -> int:
|
|
"""
|
|
floor(float) -> int
|
|
|
|
Return the floor of x as an Integral.
|
|
This is the largest integer <= x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.floor.f64(double)
|
|
%y = call double @llvm.floor.f64(double %x)
|
|
ret double %y
|
|
|
|
return int(f(x))
|
|
|
|
def fabs(x: float) -> float:
|
|
"""
|
|
fabs(float) -> float
|
|
|
|
Returns the absolute value of a floating point number.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.fabs.f64(double)
|
|
%y = call double @llvm.fabs.f64(double %x)
|
|
ret double %y
|
|
|
|
return f(x)
|
|
|
|
def fmod(x: float, y: float) -> float:
|
|
"""
|
|
fmod(float, float) -> float
|
|
|
|
Returns the remainder of x divided by y.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float, y: float) -> float:
|
|
%z = frem double %x, %y
|
|
ret double %z
|
|
|
|
return f(x, y)
|
|
|
|
def exp(x: float) -> float:
|
|
"""
|
|
exp(float) -> float
|
|
|
|
Returns the value of e raised to the xth power.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.exp.f64(double)
|
|
%y = call double @llvm.exp.f64(double %x)
|
|
ret double %y
|
|
|
|
return _check1(x, f(x), True)
|
|
|
|
def expm1(x: float) -> float:
|
|
"""
|
|
expm1(float) -> float
|
|
|
|
Return e raised to the power x, minus 1. expm1 provides
|
|
a way to compute this quantity to full precision.
|
|
"""
|
|
return _check1(x, _C.expm1(x), True)
|
|
|
|
def ldexp(x: float, i: int) -> float:
|
|
"""
|
|
ldexp(float, int) -> float
|
|
|
|
Returns x multiplied by 2 raised to the power of exponent.
|
|
"""
|
|
return _check1(x, _C.ldexp(x, i32(i)), True)
|
|
|
|
def log(x: float, base: float = e) -> float:
|
|
"""
|
|
log(float) -> float
|
|
|
|
Returns the natural logarithm (base-e logarithm) of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.log.f64(double)
|
|
%y = call double @llvm.log.f64(double %x)
|
|
ret double %y
|
|
|
|
if base == e:
|
|
return _check1(x, f(x))
|
|
else:
|
|
return _check1(x, f(x)) / _check1(base, f(base))
|
|
|
|
def log2(x: float) -> float:
|
|
"""
|
|
log2(float) -> float
|
|
|
|
Return the base-2 logarithm of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.log2.f64(double)
|
|
%y = call double @llvm.log2.f64(double %x)
|
|
ret double %y
|
|
|
|
return _check1(x, f(x))
|
|
|
|
def log10(x: float) -> float:
|
|
"""
|
|
log10(float) -> float
|
|
|
|
Returns the common logarithm (base-10 logarithm) of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.log10.f64(double)
|
|
%y = call double @llvm.log10.f64(double %x)
|
|
ret double %y
|
|
|
|
return _check1(x, f(x))
|
|
|
|
def degrees(x: float) -> float:
|
|
"""
|
|
degrees(float) -> float
|
|
|
|
Convert angle x from radians to degrees.
|
|
"""
|
|
radToDeg = 180.0 / pi
|
|
return x * radToDeg
|
|
|
|
def radians(x: float) -> float:
|
|
"""
|
|
radians(float) -> float
|
|
|
|
Convert angle x from degrees to radians.
|
|
"""
|
|
degToRad = pi / 180.0
|
|
return x * degToRad
|
|
|
|
def sqrt(x: float) -> float:
|
|
"""
|
|
sqrt(float) -> float
|
|
|
|
Returns the square root of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.sqrt.f64(double)
|
|
%y = call double @llvm.sqrt.f64(double %x)
|
|
ret double %y
|
|
|
|
return _check1(x, f(x))
|
|
|
|
def pow(x: float, y: float) -> float:
|
|
"""
|
|
pow(float, float) -> float
|
|
|
|
Returns x raised to the power of y.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float, y: float) -> float:
|
|
declare double @llvm.pow.f64(double, double)
|
|
%z = call double @llvm.pow.f64(double %x, double %y)
|
|
ret double %z
|
|
|
|
return _check2(x, y, f(x, y), True)
|
|
|
|
def acos(x: float) -> float:
|
|
"""
|
|
acos(float) -> float
|
|
|
|
Returns the arc cosine of x in radians.
|
|
"""
|
|
return _check1(x, _C.acos(x))
|
|
|
|
def asin(x: float) -> float:
|
|
"""
|
|
asin(float) -> float
|
|
|
|
Returns the arc sine of x in radians.
|
|
"""
|
|
return _check1(x, _C.asin(x))
|
|
|
|
def atan(x: float) -> float:
|
|
"""
|
|
atan(float) -> float
|
|
|
|
Returns the arc tangent of x in radians.
|
|
"""
|
|
return _check1(x, _C.atan(x))
|
|
|
|
def atan2(y: float, x: float) -> float:
|
|
"""
|
|
atan2(float, float) -> float
|
|
|
|
Returns the arc tangent in radians of y/x based
|
|
on the signs of both values to determine the
|
|
correct quadrant.
|
|
"""
|
|
return _check2(x, y, _C.atan2(y, x))
|
|
|
|
def cos(x: float) -> float:
|
|
"""
|
|
cos(float) -> float
|
|
|
|
Returns the cosine of a radian angle x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.cos.f64(double)
|
|
%y = call double @llvm.cos.f64(double %x)
|
|
ret double %y
|
|
|
|
return _check1(x, f(x))
|
|
|
|
def sin(x: float) -> float:
|
|
"""
|
|
sin(float) -> float
|
|
|
|
Returns the sine of a radian angle x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.sin.f64(double)
|
|
%y = call double @llvm.sin.f64(double %x)
|
|
ret double %y
|
|
|
|
return _check1(x, f(x))
|
|
|
|
def hypot(x: float, y: float) -> float:
|
|
"""
|
|
hypot(float, float) -> float
|
|
|
|
Return the Euclidean norm.
|
|
This is the length of the vector from the
|
|
origin to point (x, y).
|
|
"""
|
|
return _check2(x, y, _C.hypot(x, y), True)
|
|
|
|
def tan(x: float) -> float:
|
|
"""
|
|
tan(float) -> float
|
|
|
|
Return the tangent of a radian angle x.
|
|
"""
|
|
return _check1(x, _C.tan(x))
|
|
|
|
def cosh(x: float) -> float:
|
|
"""
|
|
cosh(float) -> float
|
|
|
|
Returns the hyperbolic cosine of x.
|
|
"""
|
|
return _check1(x, _C.cosh(x), True)
|
|
|
|
def sinh(x: float) -> float:
|
|
"""
|
|
sinh(float) -> float
|
|
|
|
Returns the hyperbolic sine of x.
|
|
"""
|
|
return _check1(x, _C.sinh(x), True)
|
|
|
|
def tanh(x: float) -> float:
|
|
"""
|
|
tanh(float) -> float
|
|
|
|
Returns the hyperbolic tangent of x.
|
|
"""
|
|
return _check1(x, _C.tanh(x))
|
|
|
|
def acosh(x: float) -> float:
|
|
"""
|
|
acosh(float) -> float
|
|
|
|
Return the inverse hyperbolic cosine of x.
|
|
"""
|
|
return _check1(x, _C.acosh(x))
|
|
|
|
def asinh(x: float) -> float:
|
|
"""
|
|
asinh(float) -> float
|
|
|
|
Return the inverse hyperbolic sine of x.
|
|
"""
|
|
return _check1(x, _C.asinh(x))
|
|
|
|
def atanh(x: float) -> float:
|
|
"""
|
|
atanh(float) -> float
|
|
|
|
Return the inverse hyperbolic tangent of x.
|
|
"""
|
|
return _check1(x, _C.atanh(x))
|
|
|
|
def copysign(x: float, y: float) -> float:
|
|
"""
|
|
copysign(float, float) -> float
|
|
|
|
Return a float with the magnitude (absolute value) of
|
|
x but the sign of y.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float, y: float) -> float:
|
|
declare double @llvm.copysign.f64(double, double)
|
|
%z = call double @llvm.copysign.f64(double %x, double %y)
|
|
ret double %z
|
|
|
|
return _check2(x, y, f(x, y))
|
|
|
|
def log1p(x: float) -> float:
|
|
"""
|
|
log1p(float) -> float
|
|
|
|
Return the natural logarithm of 1+x (base e).
|
|
"""
|
|
return _check1(x, _C.log1p(x))
|
|
|
|
def trunc(x: float) -> int:
|
|
"""
|
|
trunc(float) -> int
|
|
|
|
Return the Real value x truncated to an Integral
|
|
(usually an integer).
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float) -> float:
|
|
declare double @llvm.trunc.f64(double)
|
|
%y = call double @llvm.trunc.f64(double %x)
|
|
ret double %y
|
|
|
|
return int(_check1(x, f(x)))
|
|
|
|
def erf(x: float) -> float:
|
|
"""
|
|
erf(float) -> float
|
|
|
|
Return the error function at x.
|
|
"""
|
|
return _check1(x, _C.erf(x))
|
|
|
|
def erfc(x: float) -> float:
|
|
"""
|
|
erfc(float) -> float
|
|
|
|
Return the complementary error function at x.
|
|
"""
|
|
return _check1(x, _C.erfc(x))
|
|
|
|
def gamma(x: float) -> float:
|
|
"""
|
|
gamma(float) -> float
|
|
|
|
Return the Gamma function at x.
|
|
"""
|
|
return _check1(x, _C.tgamma(x), True)
|
|
|
|
def lgamma(x: float) -> float:
|
|
"""
|
|
lgamma(float) -> float
|
|
|
|
Return the natural logarithm of
|
|
the absolute value of the Gamma function at x.
|
|
"""
|
|
return _check1(x, _C.lgamma(x), True)
|
|
|
|
def remainder(x: float, y: float) -> float:
|
|
"""
|
|
remainder(float, float) -> float
|
|
|
|
Return the IEEE 754-style remainder of x with respect to y.
|
|
For finite x and finite nonzero y, this is the difference
|
|
x - n*y, where n is the closest integer to the exact value
|
|
of the quotient x / y. If x / y is exactly halfway between
|
|
two consecutive integers, the nearest even integer is used
|
|
for n.
|
|
"""
|
|
return _check2(x, y, _C.remainder(x, y))
|
|
|
|
def _gcd2(a, b):
|
|
a = abs(a)
|
|
b = abs(b)
|
|
while a:
|
|
a, b = b % a, a
|
|
return b
|
|
|
|
def gcd(*args):
|
|
"""
|
|
gcd(*args)
|
|
|
|
returns greatest common divisor of arguments.
|
|
"""
|
|
if staticlen(args) == 0:
|
|
return 0
|
|
|
|
res = args[0]
|
|
T = type(res)
|
|
|
|
if staticlen(args) == 1:
|
|
return abs(res)
|
|
|
|
for i in range(1, len(args)):
|
|
if res == T(1):
|
|
break
|
|
res = _gcd2(res, args[i])
|
|
|
|
return res
|
|
|
|
def lcm(*args):
|
|
"""
|
|
lcm(*args)
|
|
|
|
returns least common multiple of arguments.
|
|
"""
|
|
def lcm2(a, b):
|
|
return abs((a // _gcd2(a, b)) * b)
|
|
|
|
if staticlen(args) == 0:
|
|
return 1
|
|
|
|
res = args[0]
|
|
T = type(res)
|
|
|
|
if staticlen(args) == 1:
|
|
return abs(res)
|
|
|
|
for i in range(1, len(args)):
|
|
if not res:
|
|
break
|
|
res = lcm2(res, args[i])
|
|
|
|
return res
|
|
|
|
@pure
|
|
def frexp(x: float) -> Tuple[float, int]:
|
|
"""
|
|
frexp(float) -> Tuple[float, int]
|
|
|
|
The returned value is the mantissa and the integer pointed
|
|
to by exponent is the exponent. The resultant value is
|
|
x = mantissa * 2 ^ exponent.
|
|
"""
|
|
tmp = i32(0)
|
|
res = _C.frexp(float(x), __ptr__(tmp))
|
|
return (res, int(tmp))
|
|
|
|
@pure
|
|
def modf(x: float) -> Tuple[float, float]:
|
|
"""
|
|
modf(float) -> Tuple[float, float]
|
|
|
|
The returned value is the fraction component (part after
|
|
the decimal), and sets integer to the integer component.
|
|
"""
|
|
tmp = 0.0
|
|
res = _C.modf(float(x), __ptr__(tmp))
|
|
return (res, tmp)
|
|
|
|
def isclose(a: float, b: float, rel_tol: float = 1e-09, abs_tol: float = 0.0) -> bool:
|
|
"""
|
|
isclose(float, float) -> bool
|
|
|
|
Return True if a is close in value to b, and False otherwise.
|
|
For the values to be considered close, the difference between them
|
|
must be smaller than at least one of the tolerances.
|
|
"""
|
|
|
|
# short circuit exact equality -- needed to catch two
|
|
# infinities of the same sign. And perhaps speeds things
|
|
# up a bit sometimes.
|
|
if a == b:
|
|
return True
|
|
|
|
# This catches the case of two infinities of opposite sign, or
|
|
# one infinity and one finite number. Two infinities of opposite
|
|
# sign would otherwise have an infinite relative tolerance.
|
|
# Two infinities of the same sign are caught by the equality check
|
|
# above.
|
|
if a == inf or b == inf:
|
|
return False
|
|
|
|
# NAN is not close to anything, not even itself
|
|
if a == nan or b == nan:
|
|
return False
|
|
|
|
# regular computation
|
|
diff = fabs(b - a)
|
|
|
|
return ((diff <= fabs(rel_tol * b)) or (diff <= fabs(rel_tol * a))) or (
|
|
diff <= abs_tol
|
|
)
|
|
|
|
def fsum(seq):
|
|
def _fsum_realloc(p: Ptr[float], ps: Ptr[float], n: int, m: int):
|
|
from internal.gc import realloc, sizeof
|
|
v = Ptr[float]()
|
|
m += m
|
|
if n < m:
|
|
if p == ps:
|
|
v = Ptr[float](m)
|
|
str.memcpy(v.as_byte(), ps.as_byte(), n * sizeof(float))
|
|
else:
|
|
v = Ptr[float](realloc(p.as_byte(), m * sizeof(float), n * sizeof(float)))
|
|
return v, m
|
|
|
|
_NUM_PARTIALS: Static[int] = 32
|
|
ps_arr = __array__[float](_NUM_PARTIALS)
|
|
ps = ps_arr.ptr
|
|
p = ps
|
|
n, m = 0, _NUM_PARTIALS
|
|
xsave, special_sum, inf_sum = 0.0, 0.0, 0.0
|
|
hi, yr, lo = 0.0, 0.0, 0.0
|
|
|
|
for item in seq:
|
|
x = float(item)
|
|
xsave = x
|
|
i = 0
|
|
|
|
for j in range(n): # for y in partials
|
|
y = p[j]
|
|
if fabs(x) < fabs(y):
|
|
x, y = y, x
|
|
hi = x + y
|
|
yr = hi - x
|
|
lo = y - yr
|
|
if lo != 0.0:
|
|
p[i] = lo
|
|
i += 1
|
|
x = hi
|
|
|
|
n = i
|
|
if x != 0.0:
|
|
if not isfinite(x):
|
|
# a nonfinite x could arise either as
|
|
# a result of intermediate overflow, or
|
|
if isfinite(xsave):
|
|
raise OverflowError("intermediate overflow in fsum")
|
|
if isinf(xsave):
|
|
inf_sum += xsave
|
|
special_sum += xsave
|
|
# reset partials
|
|
n = 0
|
|
else:
|
|
if n >= m:
|
|
p, m = _fsum_realloc(p, ps, n, m)
|
|
p[n] = x
|
|
n += 1
|
|
|
|
if special_sum != 0.0:
|
|
if isnan(inf_sum):
|
|
raise ValueError("-inf + inf in fsum")
|
|
else:
|
|
return special_sum
|
|
|
|
hi = 0.0
|
|
if n > 0:
|
|
hi = p[n - 1]
|
|
n -= 1
|
|
# sum_exact(ps, hi) from the top, stop when the sum becomes inexact
|
|
while n > 0:
|
|
x = hi
|
|
y = p[n - 1]
|
|
n -= 1
|
|
# assert fabs(y) < fabs(x)
|
|
hi = x + y
|
|
yr = hi - x
|
|
lo = y - yr
|
|
if lo != 0.0:
|
|
break
|
|
|
|
# Make half-even rounding work across multiple partials.
|
|
# Needed so that sum([1e-16, 1, 1e16]) will round-up the last
|
|
# digit to two instead of down to zero (the 1e-16 makes the 1
|
|
# slightly closer to two). With a potential 1 ULP rounding
|
|
# error fixed-up, math.fsum() can guarantee commutativity.
|
|
if n > 0 and ((lo < 0.0 and p[n-1] < 0.0) or (lo > 0.0 and p[n-1] > 0.0)):
|
|
y = lo * 2.0
|
|
x = hi + y
|
|
yr = x - hi
|
|
if y == yr:
|
|
hi = x
|
|
|
|
return hi
|
|
|
|
def prod(iterable, start = 1):
|
|
def prod_generator(iterable: Generator[T], start, T: type):
|
|
if T is float:
|
|
result = float(start)
|
|
else:
|
|
result = start
|
|
|
|
for a in iterable:
|
|
result *= a
|
|
return result
|
|
|
|
def prod_tuple(iterable, start):
|
|
if staticlen(iterable) == 0:
|
|
return start
|
|
else:
|
|
return prod(iterable[1:], start=(start * iterable[0]))
|
|
|
|
if isinstance(iterable, Tuple):
|
|
return prod_tuple(iterable, start)
|
|
else:
|
|
return prod_generator(iterable, start)
|
|
|
|
# 32-bit float ops
|
|
|
|
e32 = float32(e)
|
|
pi32 = float32(pi)
|
|
tau32 = float32(tau)
|
|
|
|
inf32 = float32(inf)
|
|
nan32 = float32(nan)
|
|
|
|
@overload
|
|
def isnan(x: float32) -> bool:
|
|
"""
|
|
isnan(float32) -> bool
|
|
|
|
Return True if float arg is a NaN, else False.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> bool:
|
|
%y = fcmp uno float %x, 0.000000e+00
|
|
%z = zext i1 %y to i8
|
|
ret i8 %z
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def isinf(x: float32) -> bool:
|
|
"""
|
|
isinf(float32) -> bool:
|
|
|
|
Return True if float arg is an INF, else False.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> bool:
|
|
declare float @llvm.fabs.f32(float)
|
|
%a = call float @llvm.fabs.f32(float %x)
|
|
%b = fcmp oeq float %a, 0x7FF0000000000000
|
|
%c = zext i1 %b to i8
|
|
ret i8 %c
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def isfinite(x: float32) -> bool:
|
|
"""
|
|
isfinite(float32) -> bool
|
|
|
|
Return True if x is neither an infinity nor a NaN,
|
|
and False otherwise.
|
|
"""
|
|
return not (isnan(x) or isinf(x))
|
|
|
|
@overload
|
|
def ceil(x: float32) -> int:
|
|
"""
|
|
ceil(float32) -> int
|
|
|
|
Return the ceiling of x as an Integral.
|
|
This is the smallest integer >= x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.ceil.f32(float)
|
|
%y = call float @llvm.ceil.f32(float %x)
|
|
ret float %y
|
|
|
|
return int(f(x))
|
|
|
|
@overload
|
|
def floor(x: float32) -> int:
|
|
"""
|
|
floor(float32) -> int
|
|
|
|
Return the floor of x as an Integral.
|
|
This is the largest integer <= x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.floor.f32(float)
|
|
%y = call float @llvm.floor.f32(float %x)
|
|
ret float %y
|
|
|
|
return int(f(x))
|
|
|
|
@overload
|
|
def fabs(x: float32) -> float32:
|
|
"""
|
|
fabs(float32) -> float32
|
|
|
|
Returns the absolute value of a float32ing point number.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.fabs.f32(float)
|
|
%y = call float @llvm.fabs.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def fmod(x: float32, y: float32) -> float32:
|
|
"""
|
|
fmod(float32, float32) -> float32
|
|
|
|
Returns the remainder of x divided by y.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32, y: float32) -> float32:
|
|
%z = frem float %x, %y
|
|
ret float %z
|
|
|
|
return f(x, y)
|
|
|
|
@overload
|
|
def exp(x: float32) -> float32:
|
|
"""
|
|
exp(float32) -> float32
|
|
|
|
Returns the value of e raised to the xth power.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.exp.f32(float)
|
|
%y = call float @llvm.exp.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def expm1(x: float32) -> float32:
|
|
"""
|
|
expm1(float32) -> float32
|
|
|
|
Return e raised to the power x, minus 1. expm1 provides
|
|
a way to compute this quantity to full precision.
|
|
"""
|
|
return _C.expm1f(x)
|
|
|
|
@overload
|
|
def ldexp(x: float32, i: int) -> float32:
|
|
"""
|
|
ldexp(float32, int) -> float32
|
|
|
|
Returns x multiplied by 2 raised to the power of exponent.
|
|
"""
|
|
return _C.ldexpf(x, i32(i))
|
|
|
|
@overload
|
|
def log(x: float32, base: float32 = e32) -> float32:
|
|
"""
|
|
log(float32) -> float32
|
|
|
|
Returns the natural logarithm (base-e logarithm) of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.log.f32(float)
|
|
%y = call float @llvm.log.f32(float %x)
|
|
ret float %y
|
|
|
|
if base == e32:
|
|
return f(x)
|
|
else:
|
|
return f(x) / f(base)
|
|
|
|
@overload
|
|
def log2(x: float32) -> float32:
|
|
"""
|
|
log2(float32) -> float32
|
|
|
|
Return the base-2 logarithm of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.log2.f32(float)
|
|
%y = call float @llvm.log2.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def log10(x: float32) -> float32:
|
|
"""
|
|
log10(float32) -> float32
|
|
|
|
Returns the common logarithm (base-10 logarithm) of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.log10.f32(float)
|
|
%y = call float @llvm.log10.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def degrees(x: float32) -> float32:
|
|
"""
|
|
degrees(float32) -> float32
|
|
|
|
Convert angle x from radians to degrees.
|
|
"""
|
|
radToDeg = float32(180.0) / pi32
|
|
return x * radToDeg
|
|
|
|
@overload
|
|
def radians(x: float32) -> float32:
|
|
"""
|
|
radians(float32) -> float32
|
|
|
|
Convert angle x from degrees to radians.
|
|
"""
|
|
degToRad = pi32 / float32(180.0)
|
|
return x * degToRad
|
|
|
|
@overload
|
|
def sqrt(x: float32) -> float32:
|
|
"""
|
|
sqrt(float32) -> float32
|
|
|
|
Returns the square root of x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.sqrt.f32(float)
|
|
%y = call float @llvm.sqrt.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def pow(x: float32, y: float32) -> float32:
|
|
"""
|
|
pow(float32, float32) -> float32
|
|
|
|
Returns x raised to the power of y.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32, y: float32) -> float32:
|
|
declare float @llvm.pow.f32(float, float)
|
|
%z = call float @llvm.pow.f32(float %x, float %y)
|
|
ret float %z
|
|
|
|
return f(x, y)
|
|
|
|
@overload
|
|
def acos(x: float32) -> float32:
|
|
"""
|
|
acos(float32) -> float32
|
|
|
|
Returns the arc cosine of x in radians.
|
|
"""
|
|
return _C.acosf(x)
|
|
|
|
@overload
|
|
def asin(x: float32) -> float32:
|
|
"""
|
|
asin(float32) -> float32
|
|
|
|
Returns the arc sine of x in radians.
|
|
"""
|
|
return _C.asinf(x)
|
|
|
|
@overload
|
|
def atan(x: float32) -> float32:
|
|
"""
|
|
atan(float32) -> float32
|
|
|
|
Returns the arc tangent of x in radians.
|
|
"""
|
|
return _C.atanf(x)
|
|
|
|
@overload
|
|
def atan2(y: float32, x: float32) -> float32:
|
|
"""
|
|
atan2(float32, float32) -> float32
|
|
|
|
Returns the arc tangent in radians of y/x based
|
|
on the signs of both values to determine the
|
|
correct quadrant.
|
|
"""
|
|
return _C.atan2f(y, x)
|
|
|
|
@overload
|
|
def cos(x: float32) -> float32:
|
|
"""
|
|
cos(float32) -> float32
|
|
|
|
Returns the cosine of a radian angle x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.cos.f32(float)
|
|
%y = call float @llvm.cos.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def sin(x: float32) -> float32:
|
|
"""
|
|
sin(float32) -> float32
|
|
|
|
Returns the sine of a radian angle x.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.sin.f32(float)
|
|
%y = call float @llvm.sin.f32(float %x)
|
|
ret float %y
|
|
|
|
return f(x)
|
|
|
|
@overload
|
|
def hypot(x: float32, y: float32) -> float32:
|
|
"""
|
|
hypot(float32, float32) -> float32
|
|
|
|
Return the Euclidean norm.
|
|
This is the length of the vector from the
|
|
origin to point (x, y).
|
|
"""
|
|
return _C.hypotf(x, y)
|
|
|
|
@overload
|
|
def tan(x: float32) -> float32:
|
|
"""
|
|
tan(float32) -> float32
|
|
|
|
Return the tangent of a radian angle x.
|
|
"""
|
|
return _C.tanf(x)
|
|
|
|
@overload
|
|
def cosh(x: float32) -> float32:
|
|
"""
|
|
cosh(float32) -> float32
|
|
|
|
Returns the hyperbolic cosine of x.
|
|
"""
|
|
return _C.coshf(x)
|
|
|
|
@overload
|
|
def sinh(x: float32) -> float32:
|
|
"""
|
|
sinh(float32) -> float32
|
|
|
|
Returns the hyperbolic sine of x.
|
|
"""
|
|
return _C.sinhf(x)
|
|
|
|
@overload
|
|
def tanh(x: float32) -> float32:
|
|
"""
|
|
tanh(float32) -> float32
|
|
|
|
Returns the hyperbolic tangent of x.
|
|
"""
|
|
return _C.tanhf(x)
|
|
|
|
@overload
|
|
def acosh(x: float32) -> float32:
|
|
"""
|
|
acosh(float32) -> float32
|
|
|
|
Return the inverse hyperbolic cosine of x.
|
|
"""
|
|
return _C.acoshf(x)
|
|
|
|
@overload
|
|
def asinh(x: float32) -> float32:
|
|
"""
|
|
asinh(float32) -> float32
|
|
|
|
Return the inverse hyperbolic sine of x.
|
|
"""
|
|
return _C.asinhf(x)
|
|
|
|
@overload
|
|
def atanh(x: float32) -> float32:
|
|
"""
|
|
atanh(float32) -> float32
|
|
|
|
Return the inverse hyperbolic tangent of x.
|
|
"""
|
|
return _C.atanhf(x)
|
|
|
|
@overload
|
|
def copysign(x: float32, y: float32) -> float32:
|
|
"""
|
|
copysign(float32, float32) -> float32
|
|
|
|
Return a float32 with the magnitude (absolute value) of
|
|
x but the sign of y.
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32, y: float32) -> float32:
|
|
declare float @llvm.copysign.f32(float, float)
|
|
%z = call float @llvm.copysign.f32(float %x, float %y)
|
|
ret float %z
|
|
|
|
return f(x, y)
|
|
|
|
@overload
|
|
def log1p(x: float32) -> float32:
|
|
"""
|
|
log1p(float32) -> float32
|
|
|
|
Return the natural logarithm of 1+x (base e).
|
|
"""
|
|
return _C.log1pf(x)
|
|
|
|
@overload
|
|
def trunc(x: float32) -> int:
|
|
"""
|
|
trunc(float32) -> int
|
|
|
|
Return the Real value x truncated to an Integral
|
|
(usually an integer).
|
|
"""
|
|
@pure
|
|
@llvm
|
|
def f(x: float32) -> float32:
|
|
declare float @llvm.trunc.f32(float)
|
|
%y = call float @llvm.trunc.f32(float %x)
|
|
ret float %y
|
|
|
|
return int(f(x))
|
|
|
|
@overload
|
|
def erf(x: float32) -> float32:
|
|
"""
|
|
erf(float32) -> float32
|
|
|
|
Return the error function at x.
|
|
"""
|
|
return _C.erff(x)
|
|
|
|
@overload
|
|
def erfc(x: float32) -> float32:
|
|
"""
|
|
erfc(float32) -> float32
|
|
|
|
Return the complementary error function at x.
|
|
"""
|
|
return _C.erfcf(x)
|
|
|
|
@overload
|
|
def gamma(x: float32) -> float32:
|
|
"""
|
|
gamma(float32) -> float32
|
|
|
|
Return the Gamma function at x.
|
|
"""
|
|
return _C.tgammaf(x)
|
|
|
|
@overload
|
|
def lgamma(x: float32) -> float32:
|
|
"""
|
|
lgamma(float32) -> float32
|
|
|
|
Return the natural logarithm of
|
|
the absolute value of the Gamma function at x.
|
|
"""
|
|
return _C.lgammaf(x)
|
|
|
|
@overload
|
|
def remainder(x: float32, y: float32) -> float32:
|
|
"""
|
|
remainder(float32, float32) -> float32
|
|
|
|
Return the IEEE 754-style remainder of x with respect to y.
|
|
For finite x and finite nonzero y, this is the difference
|
|
x - n*y, where n is the closest integer to the exact value
|
|
of the quotient x / y. If x / y is exactly halfway between
|
|
two consecutive integers, the nearest even integer is used
|
|
for n.
|
|
"""
|
|
return _C.remainderf(x, y)
|
|
|
|
@overload
|
|
@pure
|
|
def frexp(x: float32) -> Tuple[float32, int]:
|
|
"""
|
|
frexp(float32) -> Tuple[float32, int]
|
|
|
|
The returned value is the mantissa and the integer pointed
|
|
to by exponent is the exponent. The resultant value is
|
|
x = mantissa * 2 ^ exponent.
|
|
"""
|
|
tmp = i32(0)
|
|
res = _C.frexpf(float32(x), __ptr__(tmp))
|
|
return (res, int(tmp))
|
|
|
|
@overload
|
|
@pure
|
|
def modf(x: float32) -> Tuple[float32, float32]:
|
|
"""
|
|
modf(float32) -> Tuple[float32, float32]
|
|
|
|
The returned value is the fraction component (part after
|
|
the decimal), and sets integer to the integer component.
|
|
"""
|
|
tmp = float32(0.0)
|
|
res = _C.modff(float32(x), __ptr__(tmp))
|
|
return (res, tmp)
|
|
|
|
@overload
|
|
def isclose(a: float32, b: float32, rel_tol: float32 = float32(1e-09), abs_tol: float32 = float32(0.0)) -> bool:
|
|
"""
|
|
isclose(float32, float32) -> bool
|
|
|
|
Return True if a is close in value to b, and False otherwise.
|
|
For the values to be considered close, the difference between them
|
|
must be smaller than at least one of the tolerances.
|
|
"""
|
|
|
|
# short circuit exact equality -- needed to catch two
|
|
# infinities of the same sign. And perhaps speeds things
|
|
# up a bit sometimes.
|
|
if a == b:
|
|
return True
|
|
|
|
# This catches the case of two infinities of opposite sign, or
|
|
# one infinity and one finite number. Two infinities of opposite
|
|
# sign would otherwise have an infinite relative tolerance.
|
|
# Two infinities of the same sign are caught by the equality check
|
|
# above.
|
|
if a == inf32 or b == inf32:
|
|
return False
|
|
|
|
# NAN is not close to anything, not even itself
|
|
if a == nan32 or b == nan32:
|
|
return False
|
|
|
|
# regular computation
|
|
diff = fabs(b - a)
|
|
|
|
return ((diff <= fabs(rel_tol * b)) or (diff <= fabs(rel_tol * a))) or (
|
|
diff <= abs_tol
|
|
)
|