primitive F32 is FloatingPoint[F32]
new create(value: F32 = 0) => value
new pi() => 3.14159265358979323846
new e() => 2.71828182845904523536
new _nan() => compile_intrinsic
new _inf(negative: Bool) => compile_intrinsic
new from_bits(i: U32) => compile_intrinsic
fun bits(): U32 => compile_intrinsic
new from[B: (Number & Real[B] val)](a: B) => a.f32()
new min_value() =>
"""
Minimum negative value representable.
"""
from_bits(0xFF7FFFFF)
new max_value() =>
"""
Maximum positive value representable.
"""
from_bits(0x7F7FFFFF)
new min_normalised() =>
"""
Minimum positive value representable at full precision (ie a normalised
number).
"""
from_bits(0x00800000)
new epsilon() =>
"""
Minimum positive value such that (1 + epsilon) != 1.
"""
from_bits(0x34000000)
fun tag radix(): U8 =>
"""
Exponent radix.
"""
2
fun tag precision2(): U8 =>
"""
Mantissa precision in bits.
"""
24
fun tag precision10(): U8 =>
"""
Mantissa precision in decimal digits.
"""
6
fun tag min_exp2(): I16 =>
"""
Minimum exponent value such that (2^exponent) - 1 is representable at full
precision (ie a normalised number).
"""
-125
fun tag min_exp10(): I16 =>
"""
Minimum exponent value such that (10^exponent) - 1 is representable at full
precision (ie a normalised number).
"""
-37
fun tag max_exp2(): I16 =>
"""
Maximum exponent value such that (2^exponent) - 1 is representable.
"""
128
fun tag max_exp10(): I16 =>
"""
Maximum exponent value such that (10^exponent) - 1 is representable.
"""
38
fun abs(): F32 => @"llvm.fabs.f32"[F32](this)
fun ceil(): F32 => @"llvm.ceil.f32"[F32](this)
fun floor(): F32 => @"llvm.floor.f32"[F32](this)
fun round(): F32 => @"llvm.round.f32"[F32](this)
fun trunc(): F32 => @"llvm.trunc.f32"[F32](this)
fun min(y: F32): F32 => if this < y then this else y end
fun max(y: F32): F32 => if this > y then this else y end
fun finite(): Bool =>
"""
Check whether this number is finite, ie not +/-infinity and not NaN.
"""
// True if exponent is not all 1s
(bits() and 0x7F800000) != 0x7F800000
fun infinite(): Bool =>
"""
Check whether this number is +/-infinity
"""
// True if exponent is all 1s and mantissa is 0
((bits() and 0x7F800000) == 0x7F800000) and // exp
((bits() and 0x007FFFFF) == 0) // mantissa
fun nan(): Bool =>
"""
Check whether this number is NaN.
"""
// True if exponent is all 1s and mantissa is non-0
((bits() and 0x7F800000) == 0x7F800000) and // exp
((bits() and 0x007FFFFF) != 0) // mantissa
fun ldexp(x: F32, exponent: I32): F32 =>
@ldexpf[F32](x, exponent)
fun frexp(): (F32, U32) =>
var exponent: U32 = 0
var mantissa = @frexp[F64](f64(), addressof exponent)
(mantissa.f32(), exponent)
fun log(): F32 => @"llvm.log.f32"[F32](this)
fun log2(): F32 => @"llvm.log2.f32"[F32](this)
fun log10(): F32 => @"llvm.log10.f32"[F32](this)
fun logb(): F32 => @logbf[F32](this)
fun pow(y: F32): F32 => @"llvm.pow.f32"[F32](this, y)
fun powi(y: I32): F32 =>
ifdef windows then
pow(y.f32())
else
@"llvm.powi.f32"[F32](this, y)
end
fun sqrt(): F32 =>
if this < 0.0 then
_nan()
else
@"llvm.sqrt.f32"[F32](this)
end
fun sqrt_unsafe(): F32 =>
"""
Unsafe operation.
If this is negative, the result is undefined.
"""
@"llvm.sqrt.f32"[F32](this)
fun cbrt(): F32 => @cbrtf[F32](this)
fun exp(): F32 => @"llvm.exp.f32"[F32](this)
fun exp2(): F32 => @"llvm.exp2.f32"[F32](this)
fun cos(): F32 => @"llvm.cos.f32"[F32](this)
fun sin(): F32 => @"llvm.sin.f32"[F32](this)
fun tan(): F32 => @tanf[F32](this)
fun cosh(): F32 => @coshf[F32](this)
fun sinh(): F32 => @sinhf[F32](this)
fun tanh(): F32 => @tanhf[F32](this)
fun acos(): F32 => @acosf[F32](this)
fun asin(): F32 => @asinf[F32](this)
fun atan(): F32 => @atanf[F32](this)
fun atan2(y: F32): F32 => @atan2f[F32](this, y)
fun acosh(): F32 => @acoshf[F32](this)
fun asinh(): F32 => @asinhf[F32](this)
fun atanh(): F32 => @atanhf[F32](this)
fun copysign(sign: F32): F32 => @"llvm.copysign.f32"[F32](this, sign)
fun hash(): U64 => bits().hash()
fun i128(): I128 => f64().i128()
fun u128(): U128 => f64().u128()
fun i128_unsafe(): I128 =>
"""
Unsafe operation.
If the value doesn't fit in the destination type, the result is undefined.
"""
f64_unsafe().i128_unsafe()
fun u128_unsafe(): U128 =>
"""
Unsafe operation.
If the value doesn't fit in the destination type, the result is undefined.
"""
f64_unsafe().u128_unsafe()
primitive F64 is FloatingPoint[F64]
new create(value: F64 = 0) => value
new pi() => 3.14159265358979323846
new e() => 2.71828182845904523536
new _nan() => compile_intrinsic
new _inf(negative: Bool) => compile_intrinsic
new from_bits(i: U64) => compile_intrinsic
fun bits(): U64 => compile_intrinsic
new from[B: (Number & Real[B] val)](a: B) => a.f64()
new min_value() =>
"""
Minimum negative value representable.
"""
from_bits(0xFFEF_FFFF_FFFF_FFFF)
new max_value() =>
"""
Maximum positive value representable.
"""
from_bits(0x7FEF_FFFF_FFFF_FFFF)
new min_normalised() =>
"""
Minimum positive value representable at full precision (ie a normalised
number).
"""
from_bits(0x0010_0000_0000_0000)
new epsilon() =>
"""
Minimum positive value such that (1 + epsilon) != 1.
"""
from_bits(0x3CB0_0000_0000_0000)
fun tag radix(): U8 =>
"""
Exponent radix.
"""
2
fun tag precision2(): U8 =>
"""
Mantissa precision in bits.
"""
53
fun tag precision10(): U8 =>
"""
Mantissa precision in decimal digits.
"""
15
fun tag min_exp2(): I16 =>
"""
Minimum exponent value such that (2^exponent) - 1 is representable at full
precision (ie a normalised number).
"""
-1021
fun tag min_exp10(): I16 =>
"""
Minimum exponent value such that (10^exponent) - 1 is representable at full
precision (ie a normalised number).
"""
-307
fun tag max_exp2(): I16 =>
"""
Maximum exponent value such that (2^exponent) - 1 is representable.
"""
1024
fun tag max_exp10(): I16 =>
"""
Maximum exponent value such that (10^exponent) - 1 is representable.
"""
308
fun abs(): F64 => @"llvm.fabs.f64"[F64](this)
fun ceil(): F64 => @"llvm.ceil.f64"[F64](this)
fun floor(): F64 => @"llvm.floor.f64"[F64](this)
fun round(): F64 => @"llvm.round.f64"[F64](this)
fun trunc(): F64 => @"llvm.trunc.f64"[F64](this)
fun min(y: F64): F64 => if this < y then this else y end
fun max(y: F64): F64 => if this > y then this else y end
fun finite(): Bool =>
"""
Check whether this number is finite, ie not +/-infinity and not NaN.
"""
// True if exponent is not all 1s
(bits() and 0x7FF0_0000_0000_0000) != 0x7FF0_0000_0000_0000
fun infinite(): Bool =>
"""
Check whether this number is +/-infinity
"""
// True if exponent is all 1s and mantissa is 0
((bits() and 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) and // exp
((bits() and 0x000F_FFFF_FFFF_FFFF) == 0) // mantissa
fun nan(): Bool =>
"""
Check whether this number is NaN.
"""
// True if exponent is all 1s and mantissa is non-0
((bits() and 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) and // exp
((bits() and 0x000F_FFFF_FFFF_FFFF) != 0) // mantissa
fun ldexp(x: F64, exponent: I32): F64 =>
@ldexp[F64](x, exponent)
fun frexp(): (F64, U32) =>
var exponent: U32 = 0
var mantissa = @frexp[F64](this, addressof exponent)
(mantissa, exponent)
fun log(): F64 => @"llvm.log.f64"[F64](this)
fun log2(): F64 => @"llvm.log2.f64"[F64](this)
fun log10(): F64 => @"llvm.log10.f64"[F64](this)
fun logb(): F64 => @logb[F64](this)
fun pow(y: F64): F64 => @"llvm.pow.f64"[F64](this, y)
fun powi(y: I32): F64 =>
ifdef windows then
pow(y.f64())
else
@"llvm.powi.f64"[F64](this, y)
end
fun sqrt(): F64 =>
if this < 0.0 then
_nan()
else
@"llvm.sqrt.f64"[F64](this)
end
fun sqrt_unsafe(): F64 =>
"""
Unsafe operation.
If this is negative, the result is undefined.
"""
@"llvm.sqrt.f64"[F64](this)
fun cbrt(): F64 => @cbrt[F64](this)
fun exp(): F64 => @"llvm.exp.f64"[F64](this)
fun exp2(): F64 => @"llvm.exp2.f64"[F64](this)
fun cos(): F64 => @"llvm.cos.f64"[F64](this)
fun sin(): F64 => @"llvm.sin.f64"[F64](this)
fun tan(): F64 => @tan[F64](this)
fun cosh(): F64 => @cosh[F64](this)
fun sinh(): F64 => @sinh[F64](this)
fun tanh(): F64 => @tanh[F64](this)
fun acos(): F64 => @acos[F64](this)
fun asin(): F64 => @asin[F64](this)
fun atan(): F64 => @atan[F64](this)
fun atan2(y: F64): F64 => @atan2[F64](this, y)
fun acosh(): F64 => @acosh[F64](this)
fun asinh(): F64 => @asinh[F64](this)
fun atanh(): F64 => @atanh[F64](this)
fun copysign(sign: F64): F64 => @"llvm.copysign.f64"[F64](this, sign)
fun hash(): U64 => bits().hash()
fun i128(): I128 =>
if this > I128.max_value().f64() then
return I128.max_value()
elseif this < I128.min_value().f64() then
return I128.min_value()
end
let bit = bits()
let high = (bit >> 32).u32()
let ex = ((high and 0x7FF00000) >> 20) - 1023
if ex < 0 then
return 0
end
let s = ((high and 0x80000000) >> 31).i128()
var r = ((bit and 0x000FFFFFFFFFFFFF) or 0x0010000000000000).i128()
let ex' = ex.u128()
if ex' > 52 then
r = r << (ex' - 52)
else
r = r >> (52 - ex')
end
(r xor s) - s
fun u128(): U128 =>
if this > U128.max_value().f64() then
return U128.max_value()
elseif this < U128.min_value().f64() then
return U128.min_value()
end
let bit = bits()
let high = (bit >> 32).u32()
let ex = ((high and 0x7FF00000) >> 20) - 1023
if (ex < 0) or ((high and 0x80000000) != 0) then
return 0
end
var r = ((bit and 0x000FFFFFFFFFFFFF) or 0x0010000000000000).u128()
let ex' = ex.u128()
if ex' > 52 then
r = r << (ex' - 52)
else
r = r >> (52 - ex')
end
r.u128()
fun i128_unsafe(): I128 =>
"""
Unsafe operation.
If the value doesn't fit in the destination type, the result is undefined.
"""
i128()
fun u128_unsafe(): U128 =>
"""
Unsafe operation.
If the value doesn't fit in the destination type, the result is undefined.
"""
u128()
type Float is (F32 | F64)