- [x] Backtrackable and non-backtrackable global variables via `bb_get/2`
`bb_put/2` (non-backtrackable) and `bb_b_put/2`
(backtrackable).
+- [ ] clp(B) and clp($\mathbb{Z}$) as builtin libraries (_in progress_).
- [ ] Streams and predicates for stream control (_in progress_).
- [ ] An incremental compacting garbage collector satisfying the five
properties of "Precise Garbage Collection in Prolog."
- [ ] Mode declarations.
-- [ ] Extensions for clp(FD).
## Phase 3
`abs/1`, `sin/1`, `cos/1`, `tan/1`, `asin/1`, `acos/1`,
`atan/1`, `atan2/2`, `log/1`, `exp/1`, `sqrt/1`, `float/1`,
`truncate/1`, `round/1`, `floor/1`, `ceiling/1`, `pi/0`,
- `min/1`, `max/1`
+ `min/1`, `max/1`, `gcd/2`, `sign/1`
* Comparison operators: `>`, `<`, `=<`, `>=`, `=:=`, `=\=`.
* `(:)/2`
* `(@>)/2`
"round" => Ok(ArithmeticInstruction::Round(a1, t)),
"ceiling" => Ok(ArithmeticInstruction::Ceiling(a1, t)),
"floor" => Ok(ArithmeticInstruction::Floor(a1, t)),
+ "sign" => Ok(ArithmeticInstruction::Sign(a1, t)),
"\\" => Ok(ArithmeticInstruction::BitwiseComplement(a1, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(
Constant::Atom(name, None),
"xor" => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
"mod" => Ok(ArithmeticInstruction::Mod(a1, a2, t)),
"rem" => Ok(ArithmeticInstruction::Rem(a1, a2, t)),
+ "gcd" => Ok(ArithmeticInstruction::Gcd(a1, a2, t)),
"atan2" => Ok(ArithmeticInstruction::ATan2(a1, a2, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(
Constant::Atom(name, None),
Or(ArithmeticTerm, ArithmeticTerm, usize),
Mod(ArithmeticTerm, ArithmeticTerm, usize),
Rem(ArithmeticTerm, ArithmeticTerm, usize),
+ Gcd(ArithmeticTerm, ArithmeticTerm, usize),
+ Sign(ArithmeticTerm, usize),
Cos(ArithmeticTerm, usize),
Sin(ArithmeticTerm, usize),
Tan(ArithmeticTerm, usize),
&ArithmeticInstruction::ATan2(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "rem", at_1, at_2, t)
}
+ &ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
+ }
+ &ArithmeticInstruction::Sign(ref at, t) => arith_instr_unary_functor(h, "sign", at, t),
&ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t),
&ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t),
&ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t),
"mod" => interms.push(Number::Integer(self.modulus(a1, a2)?)),
"rem" => interms.push(Number::Integer(self.remainder(a1, a2)?)),
"atan2" => interms.push(Number::Float(OrderedFloat(self.atan2(a1, a2)?))),
+ "gcd" => interms.push(Number::Integer(self.gcd(a1, a2)?)),
_ => {
return Err(self.error_form(MachineError::instantiation_error(), caller))
}
"ceiling" => interms.push(Number::Integer(self.ceiling(a1))),
"floor" => interms.push(Number::Integer(self.floor(a1))),
"\\" => interms.push(Number::Integer(self.bitwise_complement(a1)?)),
+ "sign" => interms.push(Number::Integer(self.sign(a1))),
_ => {
return Err(self.error_form(MachineError::instantiation_error(), caller))
}
}
}
+ fn gcd(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(n1.gcd(&n2))
+ }
+ (Number::Float(f), _) | (_, Number::Float(f)) => {
+ let n = Addr::Con(Constant::Float(f));
+ let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
+
+ Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub))
+ }
+ (Number::Rational(r), _) | (_, Number::Rational(r)) => {
+ let n = Addr::Con(Constant::Rational(r));
+ let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
+
+ Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub))
+ }
+ }
+ }
+
fn float_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
let f1 = result_f(&n1, rnd_f);
let f2 = result_f(&n2, rnd_f);
}
}
+ fn sign(&self, n: Number) -> Integer {
+ if n.is_positive() {
+ Integer::from(1)
+ } else if n.is_negative() {
+ Integer::from(0)
+ } else {
+ Integer::from(-1)
+ }
+ }
+
fn remainder(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
self.interms[t - 1] = try_or_fail!(self, self.int_pow(n1, n2));
self.p += 1;
}
+ &ArithmeticInstruction::Gcd(ref a1, ref a2, t) => {
+ let n1 = try_or_fail!(self, self.get_number(a1));
+ let n2 = try_or_fail!(self, self.get_number(a2));
+
+ self.interms[t - 1] = Number::Integer(try_or_fail!(self, self.gcd(n1, n2)));
+ self.p += 1;
+ }
&ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = n1.abs();
self.p += 1;
}
+ &ArithmeticInstruction::Sign(ref a1, t) => {
+ let n = try_or_fail!(self, self.get_number(a1));
+
+ self.interms[t - 1] = Number::Integer(self.sign(n));
+ self.p += 1;
+ }
&ArithmeticInstruction::Neg(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1));
&ArithmeticInstruction::RDiv(ref a1, ref a2, ref t) => {
write!(f, "rdiv {}, {}, @{}", a1, a2, t)
}
+ &ArithmeticInstruction::Gcd(ref a1, ref a2, ref t) => {
+ write!(f, "gcd {}, {}, @{}", a1, a2, t)
+ }
&ArithmeticInstruction::Shl(ref a1, ref a2, ref t) => {
write!(f, "shl {}, {}, @{}", a1, a2, t)
}
write!(f, "atan2 {}, {}, @{}", a1, a2, t)
}
&ArithmeticInstruction::Plus(ref a, ref t) => write!(f, "plus {}, @{}", a, t),
+ &ArithmeticInstruction::Sign(ref a, ref t) => write!(f, "sign {}, @{}", a, t),
&ArithmeticInstruction::Neg(ref a, ref t) => write!(f, "neg {}, @{}", a, t),
&ArithmeticInstruction::Cos(ref a, ref t) => write!(f, "cos {}, @{}", a, t),
&ArithmeticInstruction::Sin(ref a, ref t) => write!(f, "sin {}, @{}", a, t),