def fsqrt_op(config: Configuration) -> None: """ Common logic function for the float SQRT opcodes """ instruction = cast(UnOp, config.current_instruction) value = config.pop_f64() if config.enable_logic_fn_logging: logger.debug("%s(%s)", instruction.opcode.text, value) if numpy.isnan(value): with allow_invalid(): config.push_operand(numpy.sqrt(value)) elif value == 0: # TODO: this block and the subsequent _is_negative block are in # inverted order in the spec, indicating that the proper response here # should potentially be `nan` for the case of `sqrt(-0.0)` but the spec # tests assert that is not correct. # f32.wasm: line 2419 config.push_operand(value) elif _is_negative(value): config.push_operand(instruction.valtype.nan) else: config.push_operand(numpy.sqrt(value))
def ffloor_op(config: Configuration) -> None: """ Common logic function for the float FLOOR opcodes """ value = config.pop_f64() if config.enable_logic_fn_logging: logger.debug("%s(%s)", config.current_instruction.opcode.text, value) if numpy.isnan(value): with allow_invalid(): config.push_operand(numpy.floor(value)) elif numpy.isinf(value): config.push_operand(value) elif value == 0: config.push_operand(value) else: config.push_operand(numpy.floor(value))
def fabs_op(config: Configuration) -> None: """ Common logic function for the float ABS opcodes """ instruction = cast(UnOp, config.current_instruction) a = config.pop_f64() if config.enable_logic_fn_logging: logger.debug("%s(%s)", instruction.opcode.text, a) if numpy.isnan(a): if _is_negative(a): with allow_invalid(): config.push_operand(_negate_float(a)) else: config.push_operand(a) elif numpy.isinf(a): config.push_operand(instruction.valtype.inf) else: config.push_operand(numpy.abs(a))
def fnearest_op(config: Configuration) -> None: """ Common logic function for the float NEAREST opcodes """ instruction = cast(UnOp, config.current_instruction) value = config.pop_f64() if config.enable_logic_fn_logging: logger.debug("%s(%s)", instruction.opcode.text, value) if numpy.isnan(value): with allow_invalid(): config.push_operand(numpy.round(value)) elif numpy.isinf(value): config.push_operand(value) elif value == 0: config.push_operand(value) elif -0.5 <= value < 0.0: config.push_operand(instruction.valtype.negzero) else: config.push_operand(numpy.round(value))
def ftrunc_op(config: Configuration) -> None: """ Common logic function for the float TRUNC opcodes """ instruction = cast(UnOp, config.current_instruction) value = config.pop_f64() if config.enable_logic_fn_logging: logger.debug("%s(%s)", instruction.opcode.text, value) if numpy.isnan(value): with allow_invalid(): config.push_operand(numpy.trunc(value)) elif numpy.isinf(value): config.push_operand(value) elif value == 0: config.push_operand(value) elif -1.0 < value < 0.0: # TODO: `numpy.trunc` properly handles this case, can be removed. config.push_operand(instruction.valtype.negzero) else: config.push_operand(numpy.trunc(value))
def fmax_op(config: Configuration) -> None: """ Common logic function for the float MAX opcodes """ instruction = cast(BinOp, config.current_instruction) b, a = config.pop2_f64() if config.enable_logic_fn_logging: logger.debug("%s(%s, %s)", instruction.opcode.text, a, b) if numpy.isnan(a) or numpy.isnan(b): with allow_invalid(): config.push_operand(a + b) elif numpy.isposinf(a) or numpy.isposinf(b): config.push_operand(instruction.valtype.inf) elif a == 0 and b == 0: if _same_signed(a, b): config.push_operand(a) else: config.push_operand(instruction.valtype.zero) else: config.push_operand(max(a, b))