Added method Float.to_bits

This method can be used to obtain the bitwise representation of a Float.
This in turn can be used to perform an approximate equality comparison
by checking bits of a Float.
parent 57247e71
......@@ -165,6 +165,7 @@ module Inkoc
ForeignTypeAlignment
StringToInteger
StringToFloat
FloatToBits
]
.each_with_index
.each_with_object({}) { |(value, index), hash| hash[value] = index }
......
......@@ -1733,6 +1733,10 @@ module Inkoc
typedb.float_type.new_instance
end
def on_raw_float_to_bits(*)
typedb.integer_type.new_instance
end
def define_block_signature(node, scope, expected_block = nil)
define_type_parameters(node, scope)
define_argument_types(node, scope, expected_block)
......
......@@ -1493,6 +1493,10 @@ module Inkoc
raw_unary_instruction(:StringToFloat, node, body)
end
def on_raw_float_to_bits(node, body)
raw_unary_instruction(:FloatToBits, node, body)
end
def on_return(node, body)
location = node.location
register =
......
......@@ -243,6 +243,20 @@ impl Float {
def fractional -> Float {
absolute % 1.0
}
## Returns the bitwise representation of `self`, as an `Integer`.
##
## This does not _cast_ the `Float`, instead the returned `Integer` has all
## the bits set that make up `self`.
##
## # Examples
##
## Converting a `Float` to its bitwise representation:
##
## 1.0.to_bits # => 4607182418800017408
def to_bits -> Integer {
_INKOC.float_to_bits(self)
}
}
impl ToInteger for Float {
......
......@@ -373,7 +373,7 @@ test.group('std::float::Float.<=') do (g) {
assert.false(INFINITY <= 1.0)
}
g.test('Comparing INFINITY with another Infinity') {
g.test('Comparing Infinity with another Infinity') {
assert.true(INFINITY <= INFINITY)
}
}
......@@ -823,6 +823,24 @@ test.group('std::float::Float.hash') do (g) {
}
}
test.group('std::float::Float.to_bits') do (g) {
g.test('Converting a Float to its bitwise representation') {
assert.equal(1.0.to_bits, 4607182418800017408)
}
g.test('Converting a NaN to its bitwise representation') {
assert.equal(NAN.to_bits, 18444492273895866368)
}
g.test('Converting Infinity to its bitwise representation') {
assert.equal(INFINITY.to_bits, 9218868437227405312)
}
g.test('Converting negative Infinity to its bitwise representation') {
assert.equal(NEGATIVE_INFINITY.to_bits, 18442240474082181120)
}
}
test.group('std::float.parse') do (g) {
g.test('Parsing a Float') {
assert.equal(try! float.parse('1.2'), 1.2)
......
......@@ -124,3 +124,13 @@ pub fn round(
Ok(process.allocate(object_value::float(result), state.float_prototype))
}
pub fn to_bits(
state: &RcState,
process: &RcProcess,
float_ptr: ObjectPointer,
) -> Result<ObjectPointer, String> {
let bits = float_ptr.float_value()?.to_bits();
Ok(process.allocate_u64(bits, state.integer_prototype))
}
......@@ -163,6 +163,7 @@ pub enum InstructionType {
ForeignTypeAlignment,
StringToInteger,
StringToFloat,
FloatToBits,
}
/// Struct for storing information about a single instruction.
......
......@@ -1722,6 +1722,13 @@ impl Machine {
),
};
}
InstructionType::FloatToBits => {
let reg = instruction.arg(0);
let val = context.get_register(instruction.arg(1));
let res = float::to_bits(&self.state, process, val)?;
context.set_register(reg, res);
}
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment