nm->mkNode(GEQ, c, nm->mkNode(ITE, leadingZeroPos, d_one, d_zero)),
nm->mkNode(LT, c, ten));
- lem = nm->mkNode(OR, g.negate(), nm->mkNode(AND, eqs, eq, cb));
+ Node ux1lem = nm->mkNode(GEQ, n, ux1);
+
+ lem = nm->mkNode(OR, g.negate(), nm->mkNode(AND, eqs, eq, cb, ux1lem));
lem = nm->mkNode(FORALL, xbv, lem);
conc.push_back(lem);
// forall x. (x>=0 ^ x < str.len(itost)) =>
// Us( x ) = Ud( x ) ++ Us( x+1 ) ^
// U( x+1 ) = (str.code( Ud( x ) )-48) + 10*U( x ) ^
- // ite( x=0 AND str.len(itost)>1, 49, 48 ) <= str.code( Ud( x ) ) < 58
+ // ite( x=0 AND str.len(itost)>1, 49, 48 ) <= str.code( Ud( x ) ) < 58 ^
+ // n >= U(x + 1)
// ELSE
// itost = ""
// thus:
// int.to.str( n ) = itost
+ //
+ // Note: The conjunct `n >= U(x + 1)` is not needed for correctness but is
+ // just an optimization.
// In the above encoding, we use Us/Ud to introduce a chain of strings
// that allow us to refer to each character substring of itost. Notice this
Node cb =
nm->mkNode(AND, nm->mkNode(GEQ, c, d_zero), nm->mkNode(LT, c, ten));
- lem = nm->mkNode(OR, g.negate(), nm->mkNode(AND, eqs, eq, cb));
+ Node ux1lem = nm->mkNode(GEQ, stoit, ux1);
+
+ lem = nm->mkNode(OR, g.negate(), nm->mkNode(AND, eqs, eq, cb, ux1lem));
lem = nm->mkNode(FORALL, xbv, lem);
conc2.push_back(lem);
// str.len( s ) > 0 ^
// forall x. (x>=0 ^ x < str.len(s)) =>
// Us( x ) = Ud( x ) ++ Us( x+1 ) ^
- // U( x+1 ) = ( str.code( Ud( x ) ) - 48 ) + 10*U( x )
- // 48 <= str.code( Ud( x ) ) < 58
+ // U( x+1 ) = ( str.code( Ud( x ) ) - 48 ) + 10*U( x ) ^
+ // 48 <= str.code( Ud( x ) ) < 58 ^
+ // stoit >= U( x+1 )
// Thus, str.to.int( s ) = stoit
+ //
+ // Note: The conjunct `stoit >= U( x+1 )` is not needed for correctness but
+ // is just an optimization.
retNode = stoit;
}