使用Z3_mk_bvadd_no_underflow()
和Z3_mk_bvadd_no_overflow()
我感觉下溢的定义与我在文献中其他地方找到的不一致(维基百科,INTEL编程手册,stackoverflow) ,...):
我知道溢出是指加法的结果大于在给定操作数编码的位数时可以表示的最大数。这是常见的。
对于下溢,我理解(在Z3术语中)当结果小于可以在给定操作数被编码的位数的情况下表示的最小整数时。这是好的,但在文献中与我所看到的不同(例如wikipedia),因为这个概念仅适用于浮点数。
在intel编程手册中,溢出/下溢由进位和溢出标志处理:
进位标志 - 设置算术运算是否生成进位或a 借用最重要的结果;清除 除此以外。该标志表示溢出条件 无符号整数运算。它也用于多精度 算术。
溢出标志 - 设置整数结果是否过大为正 数字或太小的负数(不包括符号位)以适应 在目标操作数中;否则清除。这个标志表示一个 有符号整数(二进制补码)算术的溢出条件。
您能否确认Z3术语中下溢的确切定义?
我建议将其添加到文档中,以及减法的假定方式(从第一个操作数减去第二个操作数的第一个操作数与从第一个操作数中减去的第二个操作数),它与Z3的许多其他API保持一致。
答案 0 :(得分:1)
下溢谓词的最佳定义是代码本身,参见例如Z3_mk_bvadd_no_underflow;执行以下操作(减去参考计数):
Z3_ast Z3_API Z3_mk_bvadd_no_underflow(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
Z3_ast l1 = Z3_mk_bvslt(c, t1, zero);
Z3_ast l2 = Z3_mk_bvslt(c, t2, zero);
Z3_ast args[2] = { l1, l2 };
Z3_ast args_neg = Z3_mk_and(c, 2, args);
Z3_ast lt = Z3_mk_bvslt(c, r, zero);
Z3_ast result = Z3_mk_implies(c, args_neg, lt);
return result;
}
请注意,下溢谓词假设参数是带符号的位向量,但Z3_mk_bvsub_no_underflow
除外,它有一个启用无符号语义的标志。
对于最终评论:Z3_mk_bvsub(c,t1,t2)始终计算t1-t2
。