Skip to content
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

Merged
merged 5 commits into from
Jul 1, 2017

Conversation

telephon
Copy link
Member

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.

@telephon telephon added API change comp: sclang sclang C++ implementation (primitives, etc.). for changes to class lib use "comp: class library" enhancement labels Jun 23, 2017
@telephon
Copy link
Member Author

thanks to @brianlheim for the inspiration.

@nhthn nhthn self-assigned this Jun 26, 2017
@@ -0,0 +1,156 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leading newline

Copy link
Member Author

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 :)

callTest_commutative_lcm { |a, b|
var x = lcm(a, b);
var y = lcm(b, a);
this.assertEquals(x, y, "lcm(%, %) = lcm(%, %) should be valid"
Copy link
Contributor

@nhthn nhthn Jun 26, 2017

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.

Copy link
Member Author

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.

Copy link
Member Author

@telephon telephon Jun 29, 2017

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.

nhthn
nhthn previously approved these changes Jun 26, 2017
Copy link
Contributor

@nhthn nhthn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@nhthn nhthn dismissed their stale review June 26, 2017 21:45

approved accidentally

@telephon
Copy link
Member Author

here you are. @snappizz better?


long t;
Copy link
Contributor

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

Copy link
Member Author

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?

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Member Author

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!


test_commutative {

var operands = (-4..4).dup(2).allTuples;
Copy link
Contributor

@mossheim mossheim Jun 30, 2017

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.

Copy link
Member Author

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(changed this)

@mossheim
Copy link
Contributor

@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!

@mossheim
Copy link
Contributor

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.

Copy link
Contributor

@mossheim mossheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@telephon telephon merged commit 205ba17 into supercollider:master Jul 1, 2017
@vivid-synth
Copy link
Member

Unit tests! ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API change comp: sclang sclang C++ implementation (primitives, etc.). for changes to class lib use "comp: class library" enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants