use z3::ast::{Bool, Int};
pub fn z3_cdiv(a: &Int, b: &Int) -> Int {
let zero = Int::from_i64(0);
Bool::ite(&a.lt(&zero), &Bool::ite(&zero.lt(b), &((a + (b - 1)) / b), &((a - (b + 1)) / b)), &(a / b))
}
pub fn z3_cmod(a: &Int, b: &Int) -> Int {
a - z3_cdiv(a, b) * b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cdiv_positive() {
let solver = z3::Solver::new();
let a = Int::new_const("a");
let b = Int::new_const("b");
solver.assert(a.ge(Int::from_i64(0)));
solver.assert(b.gt(Int::from_i64(0)));
let result = z3_cdiv(&a, &b);
solver.assert(result.eq(&a / &b));
assert_eq!(solver.check(), z3::SatResult::Sat);
}
#[test]
fn test_cdiv_negative_dividend() {
let solver = z3::Solver::new();
let a = Int::from_i64(-7);
let b = Int::from_i64(3);
let result = z3_cdiv(&a, &b);
solver.assert(result.eq(Int::from_i64(-2)));
assert_eq!(solver.check(), z3::SatResult::Sat);
}
#[test]
fn test_cmod() {
let solver = z3::Solver::new();
let a = Int::from_i64(-7);
let b = Int::from_i64(3);
let result = z3_cmod(&a, &b);
solver.assert(result.eq(Int::from_i64(-1)));
assert_eq!(solver.check(), z3::SatResult::Sat);
}
}