static class · System
Math
public static class Math
- Tipo
- static class
- Espacio de nombres
- System
- Ensamblado
- System.Core
- Acceso
- public, static, abstract
- Archivo fuente
Math.ant
Herencia
- Clases base
-
AnyMath
Propiedades
Métodos
The square root; of an integer, the largest integer whose square is at most x (ISqrt).
The natural logarithm.
The logarithm in newBase; of integers, the largest power of newBase not above x (exact: 1000 in base
10 is 3, where a floating-point quotient would give 2.9999...); of an integer below 1, or in an integer
base below 2, an ArgumentError (no integer says -infinity or nan).
The logarithm in base 10 (of an integer, exact, as Log(x, 10); of an integer below 1, an ArgumentError).
The logarithm in base 2 (of an integer, exact, as Log(x, 2); of an integer below 1, an ArgumentError).
x to the power y; of integers with y >= 0, exact in the type (squaring, as many multiplications as
y has bits), where f64 would round past 2^53.
The largest integer not above x (an integer is its own).
The smallest integer not below x (an integer is its own).
The integer part, toward zero (an integer is its own).
The nearest integer; halves go to the even one (an integer is its own).
Rounded to digits decimal places (an integer is its own).
Abs<T : ISignedNumber<T>>(T x) : T
#
x without its sign.
The smaller of two numbers.
The larger of two numbers.
value within low … high.
-1, 0 or 1: the sign of x.
The largest integer whose square is at most x (x >= 0). Up to 64 bits, the f64 root corrected by division
(not by squaring, which would overflow near the type's largest value). Wider, the f64 root is only close to
53 bits: from just above it Newton's method in the type comes down to the root in a few steps.
The greatest common divisor (of the numbers without their sign).
Miembros privados e internos (39)
The nearest integer; halves go to the even one.
How many times x divides by by before it is below it (x >= 1, by >= 2): the integer logarithm.
Whether an f64 is neither NaN nor infinite.
x times 2^n, exactly (n beyond f64's exponents too).
x to an integer power, by squaring (a negative one is the reciprocal's).
The largest integer not above x: the f64-sized parts taken off one at a time (each is exact), the last below
2^52 floored and corrected by one if its f64 rounded across an integer.
Newton's method from the f64 root (doubling the exact bits each step), in f64's range by an even power of two.
Whether T has f128's 113 bits (one plus 2^-112 is above one, one plus 2^-113 rounds back to it); a constant for T.
Whether T has f256's 237 bits (one plus 2^-236 is above one, one plus 2^-237 is not); a constant for T.
ln 2.
π.
ln 10.
ln 2 = 2 atanh(1/3), its series summed until a term no longer changes the sum.
atan(1/k), its series.
π by Machin's formula: 16 atan(1/5) − 4 atan(1/239).
e^x: x − k ln 2 (|r| ≤ ½ ln 2), its series, times 2^k.
ln x: x = m·2^e (m in f64's range), Halley's method on e^y = m from the f64 logarithm, plus e ln 2.
sin x (cosine: shift 1): x − q π/2 (|r| ≤ π/4), the series of sin or cos of r by the quadrant.
atan x: Newton's method on tan y = x from the f64 arctangent.
Miembros heredados (5)
GetTypemétodo de AnyUndescribedmétodo de AnyToStringmétodo de AnyHashmétodo de Anydestroymétodo de Any
Código fuente
Math en Antril, descompilado a partir de su Larva HIR.
// System.Math — System.Core (decompiled from Larva HIR)
into namespace System
{
public static class Math
{
extern("math.sqrt") SqrtOf(f64 x) : f64;
extern("math.sin") SinOf(f64 x) : f64;
extern("math.cos") CosOf(f64 x) : f64;
extern("math.tan") TanOf(f64 x) : f64;
extern("math.asin") AsinOf(f64 x) : f64;
extern("math.acos") AcosOf(f64 x) : f64;
extern("math.atan") AtanOf(f64 x) : f64;
extern("math.atan2") Atan2Of(f64 y, f64 x) : f64;
extern("math.exp") ExpOf(f64 x) : f64;
extern("math.log") LogOf(f64 x) : f64;
extern("math.log10") Log10Of(f64 x) : f64;
extern("math.pow") PowOf(f64 x, f64 y) : f64;
extern("math.floor") FloorOf(f64 x) : f64;
extern("math.ceil") CeilingOf(f64 x) : f64;
/// The nearest integer; halves go to the even one.
RoundOf(f64 x) : f64
{
f64 low = FloorOf(x);
f64 rest = x - low;
if (rest > 0.5)
return low + 1.0;
if (rest < 0.5)
return low;
return FloorOf(low / 2.0) * 2.0 == low ? low : low + 1.0;
}
/// How many times `x` divides by `by` before it is below it (x >= 1, by >= 2): the integer logarithm.
Divisions<T : INumber<T>>(T x, T by) : T
{
T count = T.Zero;
loop (!(x < by))
{
x = x / by;
count = count + T.One;
}
return count;
}
/// Whether an f64 is neither NaN nor infinite.
Finite(f64 v) : bool => v - v == 0.0;
/// `x` times 2^n, exactly (n beyond f64's exponents too).
Scaled<T : INumber<T>>(T x, i32 n) : T
{
loop (n > 1000)
{
x = x * T.FromF64(1.0715086071862673E+301);
n = n - 1000;
}
loop (n < -1000)
{
x = x * T.FromF64(9.332636185032189E-302);
n = n + 1000;
}
return x * T.FromF64(PowOf(2.0, n));
}
/// `x` to an integer power, by squaring (a negative one is the reciprocal's).
PowInteger<T : INumber<T>>(T x, i64 n) : T
{
bool inverse = n < 0;
if (inverse)
n = -n;
T result = T.One;
T factor = x;
loop (n > 0)
{
if (n % 2 == 1)
result = result * factor;
n = n / 2;
if (n > 0)
factor = factor * factor;
}
return inverse ? T.One / result : result;
}
/// The largest integer not above `x`: the f64-sized parts taken off one at a time (each is exact), the last below
/// 2^52 floored and corrected by one if its f64 rounded across an integer.
FloorWide<T : INumber<T>>(T x) : T
{
if (!Finite(T.ToF64(x)))
return x;
T big = T.FromF64(4503599627370496.0);
T result = T.Zero;
T rest = x;
loop (!(rest < big) || !(T.Zero - big < rest))
{
T part = T.FromF64(T.ToF64(rest));
result = result + part;
rest = rest - part;
}
T low = T.FromF64(FloorOf(T.ToF64(rest)));
if (rest < low)
low = low - T.One;
else if (!(rest < low + T.One))
low = low + T.One;
return result + low;
}
CeilingWide<T : INumber<T>>(T x) : T => T.Zero - FloorWide(T.Zero - x);
RoundWide<T : INumber<T>>(T x) : T
{
T two = T.One + T.One;
T low = FloorWide(x);
T rest = x - low;
T half = T.One / two;
if (half < rest)
return low + T.One;
if (rest < half)
return low;
return FloorWide(low / two) * two == low ? low : low + T.One;
}
/// Newton's method from the f64 root (doubling the exact bits each step), in f64's range by an even power of two.
SqrtWide<T : INumber<T>>(T x) : T
{
if (!(T.Zero < x) || !Finite(T.ToF64(x)) && x == x + x)
return T.FromF64(SqrtOf(T.ToF64(x)));
i32 scale = 0;
loop (!Finite(T.ToF64(x)))
{
x = Scaled(x, -1000);
scale = scale + 500;
}
loop (T.ToF64(x) < 1E-300)
{
x = Scaled(x, 1000);
scale = scale - 500;
}
T two = T.One + T.One;
T root = T.FromF64(SqrtOf(T.ToF64(x)));
loop (i32 i = 0..8)
{
T next = (root + x / root) / two;
if (next == root)
break;
root = next;
}
return Scaled(root, scale);
}
/// Whether T has f128's 113 bits (one plus 2^-112 is above one, one plus 2^-113 rounds back to it); a constant for T.
[Inline]
Bits113<T : INumber<T>>(T unit) : bool
{
return T.One < T.One + T.FromF64(1.925929944387236E-34) && !(T.One < T.One + T.FromF64(9.62964972193618E-35));
}
/// Whether T has f256's 237 bits (one plus 2^-236 is above one, one plus 2^-237 is not); a constant for T.
[Inline]
Bits237<T : INumber<T>>(T unit) : bool
{
return T.One < T.One + T.FromF64(9.055679078826712E-72) && !(T.One < T.One + T.FromF64(4.527839539413356E-72));
}
/// ln 2.
Ln2<T : INumber<T>>(T unit) : T
{
if (Bits113(unit))
return T.FromF64(0.6931471805599453) + T.FromF64(2.3190468138462996E-17) + T.FromF64(2.8888949165808538E-34);
if (Bits237(unit))
return T.FromF64(0.6931471805599453) + T.FromF64(2.3190468138462996E-17) + T.FromF64(5.707708438416212E-34) + T.FromF64(-3.5824322106018114E-50) + T.FromF64(-1.3521668330131682E-66);
return Ln2Series(unit);
}
/// π.
PiOf<T : INumber<T>>(T unit) : T
{
if (Bits113(unit))
return T.FromF64(3.141592653589793) + T.FromF64(1.2246467991473532E-16) + T.FromF64(-3.0814879110195774E-33);
if (Bits237(unit))
return T.FromF64(3.141592653589793) + T.FromF64(1.2246467991473532E-16) + T.FromF64(-2.9947698097183397E-33) + T.FromF64(1.1124542208633653E-49) + T.FromF64(5.672205704604688E-66);
return PiSeries(unit);
}
/// ln 10.
Ln10<T : INumber<T>>(T unit) : T
{
if (Bits113(unit))
return T.FromF64(2.302585092994046) + T.FromF64(-2.1707562233822494E-16) + T.FromF64(-1.0785207688568521E-32);
if (Bits237(unit))
return T.FromF64(2.302585092994046) + T.FromF64(-2.1707562233822494E-16) + T.FromF64(-9.984262454465777E-33) + T.FromF64(-4.023357454450206E-49) + T.FromF64(1.9288994887780366E-65);
return LogWide(T.FromF64(10.0));
}
/// ln 2 = 2 atanh(1/3), its series summed until a term no longer changes the sum.
Ln2Series<T : INumber<T>>(T unit) : T
{
T z = T.One / T.FromF64(3.0);
T z2 = z * z;
T term = z;
T sum = T.Zero;
i32 n = 1;
loop (i32 i = 0..2000)
{
T next = sum + term / T.FromF64(n);
if (next == sum)
break;
sum = next;
term = term * z2;
n = n + 2;
}
return sum + sum;
}
/// atan(1/k), its series.
AtanInverse<T : INumber<T>>(T unit, i32 k) : T
{
T z = T.One / T.FromF64(k);
T z2 = z * z;
T term = z;
T sum = T.Zero;
i32 n = 1;
bool add = true;
loop (i32 i = 0..2000)
{
T part = term / T.FromF64(n);
T next = add ? sum + part : sum - part;
if (next == sum)
break;
sum = next;
term = term * z2;
n = n + 2;
add = !add;
}
return sum;
}
/// π by Machin's formula: 16 atan(1/5) − 4 atan(1/239).
PiSeries<T : INumber<T>>(T unit) : T => T.FromF64(16.0) * AtanInverse(unit, 5) - T.FromF64(4.0) * AtanInverse(unit, 239);
/// e^x: x − k ln 2 (|r| ≤ ½ ln 2), its series, times 2^k.
ExpWide<T : INumber<T>>(T x) : T
{
f64 v = T.ToF64(x);
if (!Finite(v) || v > 10000000.0 || v < -10000000.0)
return T.FromF64(ExpOf(v));
f64 k = RoundOf(v / 0.6931471805599453);
T r = x - T.FromF64(k) * Ln2(x);
T term = T.One;
T sum = T.One;
loop (i32 n = 1..1000)
{
term = term * r / T.FromF64(n);
T next = sum + term;
if (next == sum)
break;
sum = next;
}
return Scaled(sum, (i32)k);
}
/// ln x: x = m·2^e (m in f64's range), Halley's method on e^y = m from the f64 logarithm, plus e ln 2.
LogWide<T : INumber<T>>(T x) : T
{
if (!(T.Zero < x) || !Finite(T.ToF64(x)) && x == x + x)
return T.FromF64(LogOf(T.ToF64(x)));
i32 e = 0;
loop (!Finite(T.ToF64(x)))
{
x = Scaled(x, -1000);
e = e + 1000;
}
loop (T.ToF64(x) < 1E-300)
{
x = Scaled(x, 1000);
e = e - 1000;
}
T two = T.One + T.One;
T y = T.FromF64(LogOf(T.ToF64(x)));
loop (i32 i = 0..6)
{
T ey = ExpWide(y);
T next = y + two * (x - ey) / (x + ey);
if (next == y)
break;
y = next;
}
return e == 0 ? y : y + T.FromF64(e) * Ln2(x);
}
SinSeries<T : INumber<T>>(T r) : T
{
T r2 = r * r;
T term = r;
T sum = r;
i32 n = 1;
loop (i32 i = 0..1000)
{
term = T.Zero - term * r2 / T.FromF64(((f64)n + 1.0) * ((f64)n + 2.0));
n = n + 2;
T next = sum + term;
if (next == sum)
break;
sum = next;
}
return sum;
}
CosSeries<T : INumber<T>>(T r) : T
{
T r2 = r * r;
T term = T.One;
T sum = T.One;
i32 n = 0;
loop (i32 i = 0..1000)
{
term = T.Zero - term * r2 / T.FromF64(((f64)n + 1.0) * ((f64)n + 2.0));
n = n + 2;
T next = sum + term;
if (next == sum)
break;
sum = next;
}
return sum;
}
/// sin x (cosine: shift 1): x − q π/2 (|r| ≤ π/4), the series of sin or cos of r by the quadrant.
SinCosWide<T : INumber<T>>(T x, i64 shift) : T
{
f64 v = T.ToF64(x);
if (!Finite(v))
return T.FromF64(shift == 0 ? SinOf(v) : CosOf(v));
f64 q = RoundOf(v / 1.5707963267948966);
T r = x - T.FromF64(q) * (PiOf(x) / (T.One + T.One));
i64 quadrant = (((i64)q + shift) % 4 + 4) % 4;
if (quadrant == 0)
return SinSeries(r);
if (quadrant == 1)
return CosSeries(r);
if (quadrant == 2)
return T.Zero - SinSeries(r);
return T.Zero - CosSeries(r);
}
/// atan x: Newton's method on tan y = x from the f64 arctangent.
AtanWide<T : INumber<T>>(T x) : T
{
if (!Finite(T.ToF64(x)) && x == x + x || !(x == x))
return T.FromF64(AtanOf(T.ToF64(x)));
T y = T.FromF64(AtanOf(T.ToF64(x)));
loop (i32 i = 0..4)
{
T s = SinCosWide(y, 0);
T c = SinCosWide(y, 1);
T next = y - c * (s - x * c);
if (next == y)
break;
y = next;
}
return y;
}
Atan2Wide<T : INumber<T>>(T y, T x) : T
{
if (T.Zero < x)
return AtanWide(y / x);
T pi = PiOf(x);
if (x < T.Zero)
return y < T.Zero ? AtanWide(y / x) - pi : AtanWide(y / x) + pi;
if (x == T.Zero && y == y)
return T.Zero < y ? pi / (T.One + T.One) : y < T.Zero ? T.Zero - pi / (T.One + T.One) : T.Zero;
return T.FromF64(Atan2Of(T.ToF64(y), T.ToF64(x)));
}
PowWide<T : INumber<T>>(T x, T y) : T
{
f64 n = T.ToF64(y);
if (FloorWide(y) == y && Finite(n) && n < 4E+18 && n > -4E+18)
return PowInteger(x, (i64)n);
if (!(T.Zero < x))
return T.FromF64(PowOf(T.ToF64(x), n));
return ExpWide(y * LogWide(x));
}
public:
/// The square root; of an integer, the largest integer whose square is at most `x` (ISqrt).
[Inline]
Sqrt<T : INumber<T>>(T x) : T
{
return T.One / (T.One + T.One) == T.Zero ? ISqrt(x) : T.One < T.One + T.FromF64(1.1102230246251565E-16) ? SqrtWide(x) : T.FromF64(SqrtOf(T.ToF64(x)));
}
Sin<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? SinCosWide(x, 0) : T.FromF64(SinOf(T.ToF64(x)));
}
Cos<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? SinCosWide(x, 1) : T.FromF64(CosOf(T.ToF64(x)));
}
Tan<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? SinCosWide(x, 0) / SinCosWide(x, 1) : T.FromF64(TanOf(T.ToF64(x)));
}
Asin<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? Atan2Wide(x, SqrtWide(T.One - x * x)) : T.FromF64(AsinOf(T.ToF64(x)));
}
Acos<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? Atan2Wide(SqrtWide(T.One - x * x), x) : T.FromF64(AcosOf(T.ToF64(x)));
}
Atan<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? AtanWide(x) : T.FromF64(AtanOf(T.ToF64(x)));
}
Atan2<T : INumber<T>>(T y, T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? Atan2Wide(y, x) : T.FromF64(Atan2Of(T.ToF64(y), T.ToF64(x)));
}
Exp<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? ExpWide(x) : T.FromF64(ExpOf(T.ToF64(x)));
}
/// The natural logarithm.
Log<T : INumber<T>>(T x) : T
{
return T.One < T.One + T.FromF64(1.1102230246251565E-16) ? LogWide(x) : T.FromF64(LogOf(T.ToF64(x)));
}
/// The logarithm in `newBase`; of integers, the largest power of `newBase` not above `x` (exact: 1000 in base
/// 10 is 3, where a floating-point quotient would give 2.9999...); of an integer below 1, or in an integer
/// base below 2, an ArgumentError (no integer says -infinity or nan).
Log<T : INumber<T>>(T x, T newBase) : T
{
T two = T.One + T.One;
if (T.One / two == T.Zero)
{
if (x < T.One || newBase < two)
throw new ArgumentError("Math.Log: an integer's logarithm needs x >= 1 and a base >= 2");
return Divisions(x, newBase);
}
if (T.One < T.One + T.FromF64(1.1102230246251565E-16))
return LogWide(x) / LogWide(newBase);
return T.FromF64(LogOf(T.ToF64(x)) / LogOf(T.ToF64(newBase)));
}
/// The logarithm in base 10 (of an integer, exact, as `Log(x, 10)`; of an integer below 1, an ArgumentError).
Log10<T : INumber<T>>(T x) : T
{
if (T.One / (T.One + T.One) == T.Zero)
{
if (x < T.One)
throw new ArgumentError("Math.Log10: an integer's logarithm needs x >= 1");
return Divisions(x, T.FromF64(10.0));
}
if (T.One < T.One + T.FromF64(1.1102230246251565E-16))
return LogWide(x) / Ln10(x);
return T.FromF64(Log10Of(T.ToF64(x)));
}
/// The logarithm in base 2 (of an integer, exact, as `Log(x, 2)`; of an integer below 1, an ArgumentError).
Log2<T : INumber<T>>(T x) : T
{
T two = T.One + T.One;
if (T.One / two == T.Zero)
{
if (x < T.One)
throw new ArgumentError("Math.Log2: an integer's logarithm needs x >= 1");
return Divisions(x, two);
}
if (T.One < T.One + T.FromF64(1.1102230246251565E-16))
return LogWide(x) / Ln2(x);
return T.FromF64(LogOf(T.ToF64(x)) / 0.6931471805599453);
}
/// `x` to the power `y`; of integers with `y >= 0`, exact in the type (squaring, as many multiplications as
/// `y` has bits), where f64 would round past 2^53.
Pow<T : INumber<T>>(T x, T y) : T
{
T two = T.One + T.One;
if (T.One / two == T.Zero && !(y < T.Zero))
{
T result = T.One;
T factor = x;
T rest = y;
loop (T.Zero < rest)
{
if (rest % two == T.One)
result = result * factor;
rest = rest / two;
if (T.Zero < rest)
factor = factor * factor;
}
return result;
}
if (T.One < T.One + T.FromF64(1.1102230246251565E-16))
return PowWide(x, y);
return T.FromF64(PowOf(T.ToF64(x), T.ToF64(y)));
}
/// The largest integer not above `x` (an integer is its own).
[Inline]
Floor<T : INumber<T>>(T x) : T
{
return T.One / (T.One + T.One) == T.Zero ? x : T.One < T.One + T.FromF64(1.1102230246251565E-16) ? FloorWide(x) : T.FromF64(FloorOf(T.ToF64(x)));
}
/// The smallest integer not below `x` (an integer is its own).
[Inline]
Ceiling<T : INumber<T>>(T x) : T
{
return T.One / (T.One + T.One) == T.Zero ? x : T.One < T.One + T.FromF64(1.1102230246251565E-16) ? CeilingWide(x) : T.FromF64(CeilingOf(T.ToF64(x)));
}
/// The integer part, toward zero (an integer is its own).
Truncate<T : INumber<T>>(T x) : T
{
if (T.One / (T.One + T.One) == T.Zero)
return x;
if (T.One < T.One + T.FromF64(1.1102230246251565E-16))
return x < T.Zero ? CeilingWide(x) : FloorWide(x);
f64 v = T.ToF64(x);
if (v < 0.0)
return T.FromF64(CeilingOf(v));
return T.FromF64(FloorOf(v));
}
/// The nearest integer; halves go to the even one (an integer is its own).
Round<T : INumber<T>>(T x) : T
{
return T.One / (T.One + T.One) == T.Zero ? x : T.One < T.One + T.FromF64(1.1102230246251565E-16) ? RoundWide(x) : T.FromF64(RoundOf(T.ToF64(x)));
}
/// Rounded to `digits` decimal places (an integer is its own).
Round<T : INumber<T>>(T x, i32 digits) : T
{
if (T.One / (T.One + T.One) == T.Zero)
return x;
if (T.One < T.One + T.FromF64(1.1102230246251565E-16))
{
T scale = PowInteger(T.FromF64(10.0), digits);
return RoundWide(x * scale) / scale;
}
f64 factor = PowOf(10.0, digits);
return T.FromF64(RoundOf(T.ToF64(x) * factor) / factor);
}
/// `x` without its sign.
Abs<T : ISignedNumber<T>>(T x) : T => x < T.Zero ? -x : x;
/// The smaller of two numbers.
Min<T : INumber<T>>(T a, T b) : T => a < b ? a : b;
/// The larger of two numbers.
Max<T : INumber<T>>(T a, T b) : T => b < a ? a : b;
/// `value` within `low` … `high`.
Clamp<T : INumber<T>>(T value, T low, T high) : T => value < low ? low : high < value ? high : value;
/// -1, 0 or 1: the sign of `x`.
Sign<T : INumber<T>>(T x) : i32 => x < T.Zero ? -1 : T.Zero < x ? 1 : 0;
/// The largest integer whose square is at most `x` (x >= 0). Up to 64 bits, the f64 root corrected by division
/// (not by squaring, which would overflow near the type's largest value). Wider, the f64 root is only close to
/// 53 bits: from just above it Newton's method in the type comes down to the root in a few steps.
ISqrt<T : INumber<T>>(T x) : T
{
T two = T.One + T.One;
if (x < two)
return x;
T root = T.FromF64(FloorOf(SqrtOf(T.ToF64(x))));
if (T.ToF64(x) > 2.028240960365167E+31)
{
root = root + root / T.FromF64(1099511627776.0) + T.One;
loop (true)
{
T next = (root + x / root) / two;
if (!(next < root))
break;
root = next;
}
return root;
}
if (root < T.One)
root = T.One;
loop (T.One < root && x / root < root)
root = root - T.One;
loop (!(x / (root + T.One) < root + T.One))
root = root + T.One;
return root;
}
/// The greatest common divisor (of the numbers without their sign).
Gcd<T : INumber<T>>(T a, T b) : T
{
if (a < T.Zero)
a = T.Zero - a;
if (b < T.Zero)
b = T.Zero - b;
loop (!(b == T.Zero))
{
T rest = a % b;
a = b;
b = rest;
}
return a;
}
f64 PI
{
get => 3.141592653589793;
}
f64 E
{
get => 2.718281828459045;
}
f64 Tau
{
get => 6.283185307179586;
}
}
}