-
Notifications
You must be signed in to change notification settings - Fork 757
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
gcd for zero and negative numbers, including unit tests #2980
Conversation
These lattice theoretical tests are inspired by: https://en.wikipedia.org/wiki/Least_common_multiple#Lattice-theoretic and the simpler ones of: http://www.jsoftware.com/papers/eem/gcd.htm
thanks to @brianlheim for the inspiration. |
@@ -0,0 +1,156 @@ | |||
|
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.
leading newline
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 personally prefer that, just looks better to me. But if you insist :)
testsuite/classlibrary/TestLcmGcd.sc
Outdated
callTest_commutative_lcm { |a, b| | ||
var x = lcm(a, b); | ||
var y = lcm(b, a); | ||
this.assertEquals(x, y, "lcm(%, %) = lcm(%, %) should be valid" |
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 would prefer if this was a single test that checks all 81 test cases and writes "lcm(x,y) = lcm(y,x) for all x and y in [-4,4]
". that would make the post window output cleaner.
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.
yes, this is true. How would you do the test so that when some of them fail you know which ones? I ask specifically because brian convincingly argued that each test should have a smaller scope, so that it is easier to analyze.
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.
What about setting UnitTest.reportPasses = false
?
restructuring the code makes it rather unwieldy, or at least I have no idea of how to make a lightweight change here. The whole thing seems more like a limitation of the test system to express such tests.
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.
.
here you are. @snappizz better? |
|
||
long t; |
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 line and line 348 above should be removed
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.
isn't it better to explicitly declare variables that are used?
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.
oh jesus, i finally noticed where this variable is used. the better solution would be to declare it in-scope, in lines 403 and 405 below.
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.
403-406 becomes
if (a < b) {
long t = a;
a = b;
b = t;
}
while (b > 0) {
long t = a % b;
a = b;
b = t;
}
there are three software engineering/C++ style ideas in this revision:
- declare variables only in the scope where they're used
- don't use a temp variable for two separate purposes
- give each statement its own line
i get that there is a certain appeal to not modifying code beyond the minimal editing needed. there is a discussion to be had about that. what i feel is that since we've pretty much all as a team acknowledged that this code is (1) extremely old and (2) not clearly written, we should take some extra effort to clean it up a bit while we're in there. i have gone overboard in some cases ( #2861 is an example of that) but if it's a matter of writing
if (a == 0) return b;
instead of
if (a == 0)
return b;
when the first is what was done 20 years ago but the second is clearly better C++ style, i have to confess i don't see the point in sticking with the former. these are the kinds of things that i don't think we need a style guide to agree on, but maybe that is a faulty assumption since you and other contributors are not frequently working in C++. if so i am happy to go through that more transparent process.
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.
yes, just let me know, I'll try and adhere to this. Thanks!
testsuite/classlibrary/TestLcmGcd.sc
Outdated
|
||
test_commutative { | ||
|
||
var operands = (-4..4).dup(2).allTuples; |
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.
we don't need this kind of redundancy in tests. we just need to test the simplest instance and the continuation. in this case, the simplest instances are all combinations of signs (the six pairs you can make from {-1, 0, 1}
) and the continuation is the same thing including {-2, 2}
. anything more than that is wasted effort and only serves to obfuscate the purpose of the test. in this case the set (-4..4).dup(2).allTuples
is convenient notation but provides much more than what is needed in both range and combinatorics. it will test the commutative property twice on many combinations ([3, 0]
, [0, 3]
). same with line 188 below, 729 assertions where just one would do, and in line 202, 9 assertions when 5 would do.
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.
Knowing the implementation, I agree.
I had assumed that the implementation should be unknown from the perspective of the test, so that also other numbers may fail.
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.
(changed this)
@telephon btw, I do appreciate that you picked this up and wrote all these tests. it is too easy to just forget about these kinds of things. thank you so much! |
all the other conversations are purely incidental to this PR. but, if you don't mind having those discussions here, i'd like to open that dialog and see what we can do to make future PRs faster. otherwise I would be fine to merge this right now and put that conversation elsewhere. |
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.
Thanks!
Unit tests! ❤️ |
This combines a simple fix for
gcd
and unit tests.The tests were inspired by:
https://en.wikipedia.org/wiki/Least_common_multiple#Lattice-theoretic
and the simpler ones of:
http://www.jsoftware.com/papers/eem/gcd.htm
This fixes the current state and prepares for a potential future extension.