diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 8ec818e6..3ac76eff 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -743,6 +743,10 @@ enum InstructionTemplate { Ceiling(ArithmeticTerm, usize), #[strum_discriminants(strum(props(Arity = "1", Name = "floor")))] Floor(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "float_fractional_part")))] + FloatFractionalPart(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "float_integer_part")))] + FloatIntegerPart(ArithmeticTerm, usize), #[strum_discriminants(strum(props(Arity = "1", Name = "neg")))] Neg(ArithmeticTerm, usize), #[strum_discriminants(strum(props(Arity = "1", Name = "plus")))] @@ -1463,6 +1467,12 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::Floor(ref at, t) => { arith_instr_unary_functor(h, atom!("floor"), arena, at, t) } + &Instruction::FloatFractionalPart(ref at, t) => { + arith_instr_unary_functor(h, atom!("float_fractional_part"), arena, at, t) + } + &Instruction::FloatIntegerPart(ref at, t) => { + arith_instr_unary_functor(h, atom!("float_integer_part"), arena, at, t) + } &Instruction::Neg(ref at, t) => arith_instr_unary_functor( h, atom!("-"), diff --git a/src/arithmetic.rs b/src/arithmetic.rs index bc58da50..a75f2efe 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -212,6 +212,8 @@ impl<'a> ArithmeticEvaluator<'a> { atom!("round") => Ok(Instruction::Round(a1, t)), atom!("ceiling") => Ok(Instruction::Ceiling(a1, t)), atom!("floor") => Ok(Instruction::Floor(a1, t)), + atom!("float_integer_part") => Ok(Instruction::FloatIntegerPart(a1, t)), + atom!("float_fractional_part") => Ok(Instruction::FloatFractionalPart(a1, t)), atom!("sign") => Ok(Instruction::Sign(a1, t)), atom!("\\") => Ok(Instruction::BitwiseComplement(a1, t)), _ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 1)), diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 6af111b2..6be49e8d 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1053,6 +1053,16 @@ pub(crate) fn log10(n1: Number) -> Result { unary_float_fn_template(n1, |f| f.log(10f64)) } +#[inline] +pub(crate) fn float_fractional_part(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.fract()) +} + +#[inline] +pub(crate) fn float_integer_part(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.trunc()) +} + #[inline] pub(crate) fn sqrt(n1: Number) -> Result { if n1.is_negative() { @@ -1072,6 +1082,7 @@ pub(crate) fn floor(n1: Number, arena: &mut Arena) -> Number { rnd_i(&n1, arena) } + #[inline] pub(crate) fn ceiling(n1: Number, arena: &mut Arena) -> Number { let n1 = neg(n1, arena); @@ -1323,6 +1334,12 @@ impl MachineState { atom!("log10") => self.interms.push(Number::Float(OrderedFloat( drop_iter_on_err!(self, iter, log10(a1)) ))), + atom!("float_fractional_part") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, float_fractional_part(a1)) + ))), + atom!("float_integer_part") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, float_integer_part(a1)) + ))), atom!("sqrt") => self.interms.push(Number::Float(OrderedFloat( drop_iter_on_err!(self, iter, sqrt(a1)) ))), diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 8f7e3e91..fbfa6580 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -1028,6 +1028,24 @@ impl Machine { self.machine_st.interms[t - 1] = floor(n1, &mut self.machine_st.arena); self.machine_st.p += 1; } + &Instruction::FloatFractionalPart(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, float_fractional_part(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::FloatIntegerPart(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, float_integer_part(n1)) + )); + + self.machine_st.p += 1; + } &Instruction::Plus(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));