Skip to content

Commit 0bc3416

Browse files
Merge pull request #840 from allredj/test-gen-string-fix-241
Fix issue #241 - Conversion from int
2 parents 6c626c7 + 2c78d46 commit 0bc3416

File tree

1 file changed

+63
-92
lines changed

1 file changed

+63
-92
lines changed

src/solvers/refinement/string_constraint_generator_valueof.cpp

Lines changed: 63 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -267,23 +267,6 @@ string_exprt string_constraint_generatort::add_axioms_from_bool(
267267

268268
/*******************************************************************\
269269
270-
Function: smallest_by_digit
271-
272-
Inputs: number of digit
273-
274-
Outputs: an integer with the right number of digit
275-
276-
Purpose: gives the smallest integer with the specified number of digits
277-
278-
\*******************************************************************/
279-
280-
static mp_integer smallest_by_digit(int nb)
281-
{
282-
return power(10, nb-1);
283-
}
284-
285-
/*******************************************************************\
286-
287270
Function: string_constraint_generatort::add_axioms_from_int
288271
289272
Inputs: a signed integer expression, and a maximal size for the string
@@ -313,102 +296,90 @@ string_exprt string_constraint_generatort::add_axioms_from_int(
313296
exprt max=from_integer(max_size, index_type);
314297

315298
// We add axioms:
316-
// a1 : 0 <|res|<=max_size
317-
// a2 : (res[0]='-')||('0'<=res[0]<='9')
318-
319-
and_exprt a1(res.axiom_for_is_strictly_longer_than(zero),
320-
res.axiom_for_is_shorter_than(max));
299+
// a1 : i < 0 => 1 <|res|<=max_size && res[0]='-'
300+
// a2 : i >= 0 => 0 <|res|<=max_size-1 && '0'<=res[0]<='9'
301+
// a3 : |res|>1 && '0'<=res[0]<='9' => res[0]!='0'
302+
// a4 : |res|>1 && res[0]='-' => res[1]!='0'
303+
304+
binary_relation_exprt is_negative(i, ID_lt, zero);
305+
and_exprt correct_length1(
306+
res.axiom_for_is_strictly_longer_than(1),
307+
res.axiom_for_is_shorter_than(max));
308+
equal_exprt starts_with_minus(res[0], minus_char);
309+
implies_exprt a1(is_negative, and_exprt(correct_length1, starts_with_minus));
321310
axioms.push_back(a1);
322311

323-
exprt chr=res[0];
324-
equal_exprt starts_with_minus(chr, minus_char);
312+
not_exprt is_positive(is_negative);
325313
and_exprt starts_with_digit(
326-
binary_relation_exprt(chr, ID_ge, zero_char),
327-
binary_relation_exprt(chr, ID_le, nine_char));
328-
or_exprt a2(starts_with_digit, starts_with_minus);
314+
binary_relation_exprt(res[0], ID_ge, zero_char),
315+
binary_relation_exprt(res[0], ID_le, nine_char));
316+
and_exprt correct_length2(
317+
res.axiom_for_is_strictly_longer_than(0),
318+
res.axiom_for_is_strictly_shorter_than(max));
319+
implies_exprt a2(is_positive, and_exprt(correct_length2, starts_with_digit));
329320
axioms.push_back(a2);
330321

331-
// These are constraints to detect number that requiere the maximum number
332-
// of digits
333-
exprt smallest_with_max_digits=
334-
from_integer(smallest_by_digit(max_size-1), type);
335-
binary_relation_exprt big_negative(
336-
i, ID_le, unary_minus_exprt(smallest_with_max_digits));
337-
binary_relation_exprt big_positive(i, ID_ge, smallest_with_max_digits);
338-
or_exprt requieres_max_digits(big_negative, big_positive);
322+
implies_exprt a3(
323+
and_exprt(res.axiom_for_is_strictly_longer_than(1), starts_with_digit),
324+
not_exprt(equal_exprt(res[0], zero_char)));
325+
axioms.push_back(a3);
326+
327+
implies_exprt a4(
328+
and_exprt(res.axiom_for_is_strictly_longer_than(1), starts_with_minus),
329+
not_exprt(equal_exprt(res[1], zero_char)));
330+
axioms.push_back(a4);
331+
332+
assert(max_size<std::numeric_limits<size_t>::max());
339333

340334
for(size_t size=1; size<=max_size; size++)
341335
{
342336
// For each possible size, we add axioms:
343-
// all_numbers: forall 1<=i<=size. '0'<=res[i]<='9'
344-
// a3 : |res|=size&&'0'<=res[0]<='9' =>
345-
// i=sum+str[0]-'0' &&all_numbers
346-
// a4 : |res|=size&&res[0]='-' => i=-sum
347-
// a5 : size>1 => |res|=size&&'0'<=res[0]<='9' => res[0]!='0'
348-
// a6 : size>1 => |res|=size&&res[0]'-' => res[1]!='0'
349-
// a7 : size==max_size => i>1000000000
350-
exprt sum=from_integer(0, type);
351-
exprt all_numbers=true_exprt();
352-
chr=res[0];
353-
exprt first_value=typecast_exprt(minus_exprt(chr, zero_char), type);
337+
// a5 : forall 1 <= j < size. '0' <= res[j] <= '9' && sum == 10 * (sum/10)
338+
// a6 : |res| == size && '0' <= res[0] <= '9' => i == sum
339+
// a7 : |res| == size && res[0] == '-' => i == -sum
340+
341+
exprt::operandst digit_constraints;
342+
exprt sum=if_exprt(
343+
starts_with_digit,
344+
typecast_exprt(minus_exprt(res[0], zero_char), type),
345+
from_integer(0, type));
354346

355347
for(size_t j=1; j<size; j++)
356348
{
357-
chr=res[j];
358-
sum=plus_exprt(
359-
mult_exprt(sum, ten),
360-
typecast_exprt(minus_exprt(chr, zero_char), type));
361-
first_value=mult_exprt(first_value, ten);
349+
mult_exprt ten_sum(sum, ten);
350+
// sum = 10 * sum + (res[j] - '0')
351+
exprt new_sum=plus_exprt(
352+
ten_sum, typecast_exprt(minus_exprt(res[j], zero_char), type));
362353
and_exprt is_number(
363-
binary_relation_exprt(chr, ID_ge, zero_char),
364-
binary_relation_exprt(chr, ID_le, nine_char));
365-
all_numbers=and_exprt(all_numbers, is_number);
354+
binary_relation_exprt(res[j], ID_ge, zero_char),
355+
binary_relation_exprt(res[j], ID_le, nine_char));
356+
digit_constraints.push_back(is_number);
357+
358+
if(j>=max_size-1)
359+
{
360+
// check for overflows if the size is big
361+
and_exprt no_overflow(
362+
equal_exprt(sum, div_exprt(ten_sum, ten)),
363+
binary_relation_exprt(new_sum, ID_ge, ten_sum));
364+
digit_constraints.push_back(no_overflow);
365+
}
366+
sum=new_sum;
366367
}
367368

368-
axioms.push_back(all_numbers);
369+
exprt a5=conjunction(digit_constraints);
370+
axioms.push_back(a5);
369371

370372
equal_exprt premise=res.axiom_for_has_length(size);
371-
equal_exprt constr3(i, plus_exprt(sum, first_value));
372-
implies_exprt a3(and_exprt(premise, starts_with_digit), constr3);
373-
axioms.push_back(a3);
373+
implies_exprt a6(
374+
and_exprt(premise, starts_with_digit), equal_exprt(i, sum));
375+
axioms.push_back(a6);
374376

375-
implies_exprt a4(
377+
implies_exprt a7(
376378
and_exprt(premise, starts_with_minus),
377379
equal_exprt(i, unary_minus_exprt(sum)));
378-
axioms.push_back(a4);
379-
380-
// disallow 0s at the beginning
381-
if(size>1)
382-
{
383-
equal_exprt r0_zero(res[zero], zero_char);
384-
implies_exprt a5(
385-
and_exprt(premise, starts_with_digit),
386-
not_exprt(r0_zero));
387-
axioms.push_back(a5);
388-
389-
exprt one=from_integer(1, index_type);
390-
equal_exprt r1_zero(res[one], zero_char);
391-
implies_exprt a6(
392-
and_exprt(premise, starts_with_minus),
393-
not_exprt(r1_zero));
394-
axioms.push_back(a6);
395-
}
396-
397-
// when the size is close to the maximum, either the number is very big
398-
// or it is negative
399-
if(size==max_size-1)
400-
{
401-
implies_exprt a7(premise, or_exprt(requieres_max_digits,
402-
starts_with_minus));
403-
axioms.push_back(a7);
404-
}
405-
// when we reach the maximal size the number is very big in the negative
406-
if(size==max_size)
407-
{
408-
implies_exprt a7(premise, and_exprt(starts_with_minus, big_negative));
409-
axioms.push_back(a7);
410-
}
380+
axioms.push_back(a7);
411381
}
382+
412383
return res;
413384
}
414385

0 commit comments

Comments
 (0)