-
Notifications
You must be signed in to change notification settings - Fork 274
Intervals with tests #5361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Intervals with tests #5361
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #5361 +/- ##
=========================================
Coverage 68.14% 68.14%
=========================================
Files 1171 1173 +2
Lines 96641 97333 +692
=========================================
+ Hits 65858 66331 +473
- Misses 30783 31002 +219
Continue to review full report at Codecov.
|
I've added test for binary |
Added to_string tests and squashed clang format changes into the original commit that introduces them |
963d5b5
to
b9e275b
Compare
Removed the changes to interval_template, one into separate PR: #5362, the other changes essentially cancelled themselves out, so I just removed them both. |
CI failure is lint - will fix, but ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some things to check, but as you say happy to get this in then fix it up subsequently. I didn't look at the big "fix crap after rebase" commit or the huge 2000-line "add intervals" one due to lack of time.
unit/util/interval/to_string.cpp
Outdated
@@ -0,0 +1,52 @@ | |||
/*******************************************************************\ | |||
Module: Unit tests for variable/sensitivity/abstract_object::merge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong header
REQUIRE(five.eval(ID_minus, eight) == interval_of(-3)); | ||
REQUIRE(five.eval(ID_mult, eight) == interval_of(40)); | ||
REQUIRE(five.eval(ID_div, eight) == interval_of(0)); | ||
REQUIRE(five.eval(ID_mod, eight) == interval_from_to(0, 5)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking this oddity is known
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is but i've added a comment to highlight it.
@@ -103,3 +103,62 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") | |||
} | |||
} | |||
} | |||
|
|||
TEST_CASE("binary eval switch", "[core][analyses][interval]") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment that this only considers singletons?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess - the reason for only considering singletons is each of the opertions is tested seperatly with both singleton and ranges, this test is really to check eval dispatches to the correct function
unit/util/interval/comparisons.cpp
Outdated
// REQUIRE(two_to_four.equal(six_to_eight).is_unknown()); | ||
REQUIRE_FALSE(two_to_four.equal(five_to_ten).is_true()); | ||
|
||
REQUIRE_FALSE(two_to_four.not_equal(six_to_eight).is_unknown()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does the not-unknown one use six_to_eight but the others use five_to_ten?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this seems like a confusing mess - I've broken it into 3 sections - same interval, overlapping interval, disjoint interval and used consistent intervals for equal and not equal.
REQUIRE(V(a_mod_b.get_upper()) == 5); | ||
|
||
const auto b_mod_a = b.modulo(a); | ||
// TODO: precision with single element modulo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add commented-out the results you would expect when fixed. Got a ticket for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No - it isn't wrong and we have no intention to fix it any time soon - a ticket will just sit not getting done. I would only raise it once someone actually wanted this to be more precise. Perhaps TODO is wrong, perhaps should just say note modulo is very imprecise.
unit/util/interval/eval.cpp
Outdated
auto upper_value = numeric_cast<mp_integer>( | ||
five_to_eight.eval(ID_unary_minus).get_upper()); | ||
REQUIRE(upper_value.has_value()); | ||
REQUIRE(upper_value.value() == -8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Known bug that -((5, 8)) == (-8, -8)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo that gets fixed in later commit
unit/util/interval/eval.cpp
Outdated
THEN("When we apply unary subtraction to it, it should be negated") | ||
{ | ||
auto negated_val = numeric_cast<mp_integer>( | ||
five_to_eight.eval(ID_unary_minus).get_lower()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compare equality against expected interval?
src/util/interval.cpp
Outdated
lower.type() = type; | ||
if(this->type().id() == ID_bool && is_int(type)) | ||
{ | ||
unsigned lower_num = !has_no_lower_bound() && get_lower().is_true(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has-no-lower-bound but get-lower returns something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well it has a not
before the has_no_lower_bound
-This function is one of the functions I don't really get, but would want to tidy up only after the code that is already using it is merged so I can change both at the same time if necessary
unit/util/interval/subtract.cpp
Outdated
WHEN("Subtracting two constant intervals") | ||
{ | ||
auto lhs = | ||
constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use from_integer and perhaps binary numeric literals if you want to emphasise the bitpattern you intend. I think these might be broken too because constant_exprt expects hex representation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This thankfully ends up going away
@@ -105,15 +105,16 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const | |||
} | |||
|
|||
constant_interval_exprt | |||
constant_interval_exprt::minus(const constant_interval_exprt &o) const | |||
constant_interval_exprt::minus(const constant_interval_exprt &other) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split commit "Remove swap function in intervals Also, refactor minus and correct a typo in the comments" to do one thing at a time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go on then - since it's your last day 😛
(INT) Interval values
As it stands in conflicted with the method from exprt
So they don't conflict with the exprt methods
Also, mark them as explicit where appropriate and add some documentation
Also replace some asserts with INVARIANT, PRECONDITION or UNREACHABLE
Also left some comments for things that need to be cleaned up in the future
Currently checks are equivalent intervals, but before wasn't even checking that
ireps now use hex encoding, updated to modern version to get string of number
These aren't currently supported and cause a crash when executed
Currently this returns top rather than the actual range
Move some shift tests from the bitwise set of tests
Was wrongly using the unary negation operator, rather than subtracting one interval from the other.
4e39366
to
1d92ca0
Compare
A note to reviewers, this PR, though large, is entirely an isolated addition
util/interval
. There are lots of ways this code could be improved (I've listed some in #5203) since VSD is based on top of this, I propose merging as is, and then applying fixes after - so I'd encourage not going through this with a fine tooth comb to find the ways it is wrong!This is a rebase of #5203 that addresses I believe the most pressing issues:
eval(ID_minus)
Some gaps in the tests remain:
logical_or
/logical_and
/logical_xor
I believe these functions should be removed, and there just be a single method to get the range as a tvt, and then have these functions implemented on tvt. As such, I didn't write the tests.
code in the
generate_*
andappend_*
functionsThe semantics of these aren't clear to me, and shouldn't be part of the public interface. Probably the code that is uncovered will be hard to cover if the interface is tidier
trivial type getters and constructors
There are loads of these, and they mostly need to be deleted. To avoid breaking, I recommend waiting until VSD is merged before deleting. However, not worth testing in the meantime.
wrappers
interval.cpp implements all of the calling conventions. This wants tidying up, but in the meantime I've not bothered to test every possible calling syntax.
typecast
This is worth testing, but I don't understand what it's doing and it seems fishy. However, it is used in VSD so I'll leave for now, so it can be tested / removed after VSD is merged.
TBH in the brief time I've spent with this, there are a bunch of bugs and inconsistencies here, if there wasn't a mountain of work built on top of it, I'd recommend breaking this into something smaller than works (e.g. remove the untested or broken functionality). However, this isn't really an option, so I suggest we merge like this, merge VSD and perhaps immediately remove the interval portion of the VSD, along with this, and reintroduce it gradually (allowing at least the bulk of VSD to be merged).