f32/f64toParts in repl only

This commit is contained in:
Fabian Schmalzried 2024-03-16 14:41:20 +01:00
parent 64e9899cad
commit 473b8ef2d3
No known key found for this signature in database
GPG key ID: D691D5DA4CEF42E7
12 changed files with 72 additions and 6 deletions

View file

@ -111,6 +111,8 @@ comptime {
exportNumFn(num.lessThanOrEqualU128, "less_than_or_equal.u128");
exportNumFn(num.greaterThanU128, "greater_than.u128");
exportNumFn(num.greaterThanOrEqualU128, "greater_than_or_equal.u128");
exportNumFn(num.f32ToParts, "f32_to_parts");
exportNumFn(num.f64ToParts, "f64_to_parts");
inline for (INTEGERS, 0..) |T, i| {
num.exportPow(T, ROC_BUILTINS ++ "." ++ NUM ++ ".pow_int.");

View file

@ -15,6 +15,18 @@ pub fn NumParseResult(comptime T: type) type {
};
}
pub const F32Parts = extern struct {
fraction: u32,
exponent: u8,
sign: bool,
};
pub const F64Parts = extern struct {
fraction: u64,
exponent: u16,
sign: bool,
};
pub const U256 = struct {
hi: u128,
lo: u128,
@ -630,3 +642,21 @@ pub fn exportCountOneBits(comptime T: type, comptime name: []const u8) void {
}.func;
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
}
pub fn f32ToParts(self: f32) callconv(.C) F32Parts {
const u32Value = @as(u32, @bitCast(self));
return F32Parts{
.fraction = u32Value & 0x7fffff,
.exponent = @truncate(u32Value >> 23 & 0xff),
.sign = u32Value >> 31 & 1 == 1,
};
}
pub fn f64ToParts(self: f64) callconv(.C) F64Parts {
const u64Value = @as(u64, @bitCast(self));
return F64Parts{
.fraction = u64Value & 0xfffffffffffff,
.exponent = @truncate(u64Value >> 52 & 0x7ff),
.sign = u64Value >> 63 & 1 == 1,
};
}

View file

@ -151,7 +151,9 @@ interface Num
toF64,
toF64Checked,
withoutDecimalPoint,
withDecimalPoint
withDecimalPoint,
f32ToParts,
f64ToParts
]
imports [
Bool.{ Bool },
@ -1410,8 +1412,12 @@ toF32Checked : Num * -> Result F32 [OutOfBounds]
toF64Checked : Num * -> Result F64 [OutOfBounds]
## Turns a [Dec] into its [I128] representation, effectifely removing the decimal point.
## Turns a [Dec] into its [I128] representation by removing the decimal point.
withoutDecimalPoint : Dec -> I128
## Turns a [I128] into the coresponding [Dec], effectifely addoing the decimal point.
withDecimalPoint : I128 -> Dec
## Turns a [I128] into the coresponding [Dec] by adding the decimal point.
withDecimalPoint : I128 -> Dec
f32ToParts: F32 -> { sign : Bool, exponent : U8, fraction : U32 }
f64ToParts: F64 -> { sign : Bool, exponent : U16, fraction : U64 }

View file

@ -334,6 +334,8 @@ pub const NUM_COUNT_LEADING_ZERO_BITS: IntrinsicName =
pub const NUM_COUNT_TRAILING_ZERO_BITS: IntrinsicName =
int_intrinsic!("roc_builtins.num.count_trailing_zero_bits");
pub const NUM_COUNT_ONE_BITS: IntrinsicName = int_intrinsic!("roc_builtins.num.count_one_bits");
pub const NUM_F32_TO_PARTS: &str = "roc_builtins.num.f32_to_parts";
pub const NUM_F64_TO_PARTS: &str = "roc_builtins.num.f64_to_parts";
pub const STR_INIT: &str = "roc_builtins.str.init";
pub const STR_COUNT_SEGMENTS: &str = "roc_builtins.str.count_segments";

View file

@ -207,6 +207,8 @@ map_symbol_to_lowlevel_and_arity! {
I128OfDec; I128_OF_DEC; 1,
NumWithoutDecimalPoint; NUM_WITHOUT_DECIMAL_POINT; 1,
NumWithDecimalPoint; NUM_WITH_DECIMAL_POINT; 1,
NumF32ToParts; NUM_F32_TO_PARTS; 1,
NumF64ToParts; NUM_F64_TO_PARTS; 1,
Eq; BOOL_STRUCTURAL_EQ; 2,
NotEq; BOOL_STRUCTURAL_NOT_EQ; 2,

View file

@ -2039,6 +2039,16 @@ trait Backend<'a> {
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout)
}
LowLevel::NumF32ToParts => {
let intrinsic = bitcode::NUM_F32_TO_PARTS.to_string();
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout)
}
LowLevel::NumF64ToParts => {
let intrinsic = bitcode::NUM_F64_TO_PARTS.to_string();
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout)
}
x => todo!("low level, {:?}", x),
}
}

View file

@ -1176,6 +1176,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
arguments!(arg);
arg
}
NumF32ToParts => todo!("NumF32ToParts"),
NumF64ToParts => todo!("NumF64ToParts"),
Eq => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));

View file

@ -2103,6 +2103,8 @@ impl<'a> LowLevelCall<'a> {
SetJmp | LongJmp | SetLongJmpBuffer => {
unreachable!("only inserted in dev backend codegen")
}
NumF32ToParts => todo!("NumF32ToParts"),
NumF64ToParts => todo!("NumF64ToParts"),
}
}

View file

@ -104,6 +104,8 @@ pub enum LowLevel {
NumCountOneBits,
NumWithoutDecimalPoint,
NumWithDecimalPoint,
NumF32ToParts,
NumF64ToParts,
I128OfDec,
Eq,
NotEq,
@ -341,6 +343,8 @@ map_symbol_to_lowlevel! {
I128OfDec <= I128_OF_DEC;
NumWithoutDecimalPoint <= NUM_WITHOUT_DECIMAL_POINT;
NumWithDecimalPoint <= NUM_WITH_DECIMAL_POINT;
NumF32ToParts <= NUM_F32_TO_PARTS;
NumF64ToParts <= NUM_F64_TO_PARTS;
Eq <= BOOL_STRUCTURAL_EQ;
NotEq <= BOOL_STRUCTURAL_NOT_EQ;
And <= BOOL_AND;

View file

@ -1270,6 +1270,8 @@ define_builtins! {
158 NUM_REM_UNCHECKED: "remUnchecked" // traps on division by zero
159 NUM_WITHOUT_DECIMAL_POINT: "withoutDecimalPoint"
160 NUM_WITH_DECIMAL_POINT: "withDecimalPoint"
161 NUM_F32_TO_PARTS: "f32ToParts"
162 NUM_F64_TO_PARTS: "f64ToParts"
}
4 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias

View file

@ -1592,7 +1592,9 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC {
| NumToFloatChecked
| NumCountLeadingZeroBits
| NumCountTrailingZeroBits
| NumCountOneBits => RC::NoRc,
| NumCountOneBits
| NumF32ToParts
| NumF64ToParts => RC::NoRc,
I128OfDec | NumWithoutDecimalPoint | NumWithDecimalPoint => RC::NoRc,
DictPseudoSeed => RC::NoRc,
StrStartsWith | StrEndsWith => RC::NoRc,

View file

@ -1347,7 +1347,9 @@ pub(crate) fn lowlevel_borrow_signature(op: LowLevel) -> &'static [Ownership] {
| NumCountOneBits
| I128OfDec
| NumWithoutDecimalPoint
| NumWithDecimalPoint => &[IRRELEVANT],
| NumWithDecimalPoint
| NumF32ToParts
| NumF64ToParts => &[IRRELEVANT],
StrStartsWith | StrEndsWith => &[BORROWED, BORROWED],
StrFromUtf8 => &[OWNED],
StrToUtf8 => &[OWNED],