Feature #5190
closed[solver] Поддержка целочисленного переполнения
100%
Description
При генерации тестов потребовалось выполнить выражение (ADD -1487988057 -1487988057) для типа данных INTEGER. Вылетело следующее исключение:
java.lang.NumberFormatException: For input string: "-2975976114"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.valueOf(Unknown Source)
at ru.ispras.fortress.data.DataTypeId$3.valueOf(DataTypeId.java:125)
at ru.ispras.fortress.data.DataType.valueOf(DataType.java:197)
at ru.ispras.fortress.solver.engine.z3.Z3TextSolver.parseVariable(Z3TextSolver.java:212)
at ru.ispras.fortress.solver.engine.z3.Z3TextSolver.tryToParseVariable(Z3TextSolver.java:238)
at ru.ispras.fortress.solver.engine.z3.Z3TextSolver.solve(Z3TextSolver.java:144)
...
Updated by Igor Melnichenko over 10 years ago
- Priority changed from Normal to High
Updated by Andrei Tatarnikov over 10 years ago
А пример кода для воспроизведения можно прислать?
Updated by Igor Melnichenko over 10 years ago
Каюсь, неправильно сформулировал: проблема возникает не на этапе сложения, а на этапе выполнения операции (EQ INTEGER -2975976114)
ConstraintBuilder builder = new ConstraintBuilder();
builder.setName("Arithmetic");
builder.setKind(ConstraintKind.FORMULA_BASED);
builder.setDescription("Arithmetic constraint");
NodeVariable a = new NodeVariable(builder.addVariable("a", DataType.INTEGER));
NodeValue value = new NodeValue(DataType.INTEGER.valueOf("-1487988057", 10));
NodeExpr sum = new NodeExpr(StandardOperation.ADD, value, value);
builder.setInnerRep(new Formulas(new NodeExpr(StandardOperation.EQ, a, sum)));
onstraint c = builder.build();
c.getKind().getDefaultSolverId().getSolver().solve(c);
Updated by Andrei Tatarnikov over 10 years ago
Ошибка происходит при попытке распарсить результат Z3 - число -2975976114. Оно не вмещается в тип Java int, который используется в Fortress для реализации типа SMT-LIB Int.
int x1 = -1487988057;
int y1 = -2975976114; // Не скомпилируется
int x2 = Integer.valueOf("-1487988057");
int y2 = Integer.valueOf("-2975976114"); // Сгенерирует исключение
Чтобы поддерживать числа, выходящие за пределы Java int, нужно менять внутреннюю реализацию DataTypeId.LOGIC_INTEGER (перейти на long или BigInteger). Должен заметить, что тип SMT-LIB Int - безразмерный и не будет переполняться, какие бы числа не складывалить. Если нужно работать с данными фиксированного размера, то нужно использовать битовые вектора.
Updated by Igor Melnichenko over 10 years ago
Мне кажется, имеет смысл добавить переполняемый знаковый целочисленный тип данных, соответствующий int'у из Java и integer'у из Verilog'а, для которого будет выполняться равенство -1487988057 - 1487988057 = 1318991182.
Updated by Andrei Tatarnikov over 10 years ago
В SMT-LIB есть только один тип Int и он работает так:
Код, сгенерированый Fortress:
(declare-const a Int)
(assert (= a (+ (- 1487988057) (- 1487988057))))
(check-sat)
(get-value ( a))
(get-model)
(exit)
Результат работы Z3:
sat
((a (- 2975976114)))
(model
(define-fun a () Int
(- 2975976114))
)
Int фиксированный длины нужно будет реализовывать как обёртку вокруг BIT_VECTOR. Т.е., что бы для данного ограничения генерировался код
(declare-const a (_ BitVec 32))
(assert (= a (bvadd (bvneg (_ bv1487988057 32)) (bvneg (_ bv1487988057 32)))))
(check-sat)
(get-value ( a))
(get-model)
(exit)
который даст результат:
sat
((a #x4e9e354e))
(model
(define-fun a () (_ BitVec 32)
#x4e9e354e)
)
#x4e9e354e - это 1318991182
Такое ограничение можно написать самостоятельно. Методы преобразования int в битововый вектор и обратно в классе BitVector есть. Нужно ли это автоматизировать пусть решает Саша.
Updated by Alexander Kamkin over 10 years ago
- Subject changed from Поддержка целочисленного переполнения to [solver] Поддержка целочисленного переполнения
- Игорю предлагаю использовать битовые вектора. Безразмерные целые типы в описании аппаратуры - это странность.
- Андрею предлагаю подумать над возможностью использования
BigInteger
.
Updated by Andrei Tatarnikov about 10 years ago
- Priority changed from High to Normal
Андрею предлагаю подумать над возможностью использования BigInteger.
Сделаю, по чуть попозже.
Updated by Sergey Smolov about 10 years ago
- Priority changed from Normal to High
Updated by Alexander Kamkin about 10 years ago
Андрей, "чуть попозже" длится 2 месяца.
Updated by Andrei Tatarnikov about 10 years ago
- Status changed from New to Resolved
- % Done changed from 0 to 100
Сделано. См. r645 и r646.
Updated by Andrei Tatarnikov almost 10 years ago
- Status changed from Resolved to Closed
- Published in build set to 141226