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

Add function gcd #539

Merged
merged 1 commit into from
Oct 1, 2021
Merged

Add function gcd #539

merged 1 commit into from
Oct 1, 2021

Conversation

Sideboard
Copy link
Contributor

Closes #515

  1. Add elemental integer function gcd to calculate the greatest common divisor of two numbers
    a. Handle negative input as positive
  2. Add tests (special, normal, swapped, negative, integer kinds)

@Sideboard
Copy link
Contributor Author

I appreciate tips about tests. More, less, special cases …

@awvwgk awvwgk added reviewers needed This patch requires extra eyes topic: mathematics linear algebra, sparse matrices, special functions, FFT, random numbers, statistics, ... labels Sep 26, 2021
@milancurcic
Copy link
Member

Thanks @Sideboard, the implementation looks good to me. Tests seem fine as well.

We should add the FORD docstrings to the function, and the spec as well. You can look at other functions for examples. Let us know if you need help with that.

General question for everybody, do we have a guide on when to put a function implementation in its own submodule and when to leave it in the module? I see that we have clip in the module but the others have their own submodules.

@Sideboard
Copy link
Contributor Author

Ok, I can add them. I looked at clip for reference. Thought it was in the main file because of its size. The subfile question extends to the corresponding tests.

@Sideboard
Copy link
Contributor Author

The spec only says "integer" and "another integer" for now.

@aslozada
Copy link
Member

aslozada commented Sep 26, 2021

I appreciate tips about tests. More, less, special cases …

A test with nested functions, maybe.
gcd(a,gcd(b,gcd(c,gcd(e,gcd(f,...gcd(y,z))))))

@Sideboard
Copy link
Contributor Author

Sideboard commented Sep 27, 2021

A test with nested functions, maybe.
gcd(a,gcd(b,gcd(c,gcd(e,gcd(f,...gcd(y,z))))))

Does this really test anything new? If gcd(y, z) correctly returns yz what does gcd(x, yz) tell us?

Is there interest in a version of gcd that works with a rank-1 array for more than two arguments?

@Carltoffel
Copy link
Member

Carltoffel commented Sep 27, 2021

Is there interest in a version of gcd that works with a rank-1 array for more than two arguments?

What do you mean? Could you give an example, please?

Edit: Something like gcd([20, 30, 40]) -> 10?

@Sideboard
Copy link
Contributor Author

Edit: Something like gcd([20, 30, 40]) -> 10?

Yes, that's what I mean.

@ivan-pi
Copy link
Member

ivan-pi commented Sep 27, 2021

General question for everybody, do we have a guide on when to put a function implementation in its own submodule and when to leave it in the module? I see that we have clip in the module but the others have their own submodules.

On the long term I think the public modules should contain only the interfaces, and all of the implementation should be placed in sub-modules. This would facilitate compiler vendors providing their own optimized implementations in the (distant?) future. It would also make it easier to swap between debug and release binaries by re-linking. I think the current reasoning was simply when launching a new module with a small function, it was just easier to prepare a single module.

A second reason in favor of separating interface and implementation might be to use a stdlib library compiled by another Fortran compiler. In this case you would only need to compile the interface (see #530 (comment) and the discussion that follows). As an example, Intel MKL ships libraries that can be used with both Intel and gfortran compilers.

@milancurcic, should I make a new issue to discuss this? We can then edit the developer docs in a new PR.

@milancurcic
Copy link
Member

Yes @ivan-pi, thanks, that would be good.

@Sideboard
Copy link
Contributor Author

Should anything be changed for this PR?

Copy link
Member

@aman-godara aman-godara left a comment

Choose a reason for hiding this comment

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

Looks great to me! I have left few comments, some of them are just open ended question for everyone. Thank you @Sideboard.

src/stdlib_math.fypp Outdated Show resolved Hide resolved
doc/specs/stdlib_math.md Outdated Show resolved Hide resolved
doc/specs/stdlib_math.md Show resolved Hide resolved
doc/specs/stdlib_math.md Outdated Show resolved Hide resolved
Copy link
Member

@14NGiestas 14NGiestas left a comment

Choose a reason for hiding this comment

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

There is only a minor (non-)issue about the wording in the docs but I believe this is good to go.

src/stdlib_math.fypp Show resolved Hide resolved
Copy link
Member

@ivan-pi ivan-pi left a comment

Choose a reason for hiding this comment

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

Thanks @14NGiestas for the interesting link. There was a nice response to that blog post from Prof Daniel Lemire (@lemire).

Pending the small issues in the documentation, I approve merging this.

Comment on lines 305 to 306
!>
!> Version: experimental
Copy link
Member

Choose a reason for hiding this comment

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

I think a comment stating the (current) implementation uses the "Euclidean algorithm" would be helpful.

In the future a competing implementation might use another algorithm.

Comment on lines 106 to 107
call check(gcd(-9_int8, 6_int8) == 3_int8, 'gcd failed for gcd(-9, 6)', warn=.true.)
call check(gcd(9_int8, -6_int8) == 3_int8, 'gcd failed for gcd(9, -6)', warn=.true.)
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps another test with negative a and b = 0 would be good, just to verify the limit case gcd(a,0) == abs(a) is indeed true.

Copy link
Member

Choose a reason for hiding this comment

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

@Sideboard this test case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added (0, -2). Now I see that it's not exactly what was asked for but probably close enough.

doc/specs/stdlib_math.md Show resolved Hide resolved
@Sideboard
Copy link
Contributor Author

Is there a consensus on where the annotation should be, the interface or the implementation?

@Sideboard
Copy link
Contributor Author

Sideboard commented Sep 29, 2021

Both descriptive (e.g. "Converts …") and imperative ("Convert …") formulations can be found among the function annotations.

@aman-godara
Copy link
Member

aman-godara commented Oct 1, 2021

@milancurcic this still needs one more approval to be merged.

@Sideboard small change is required, see this.

@Sideboard
Copy link
Contributor Author

I thought the approvals were invalidated when I pushed to the branch but a grey check mark means that the reviewer does not have write-access necessary for the merge. Should I request a review from someone with those rights? Who?

@milancurcic
Copy link
Member

Thanks all, let's merge it.

@milancurcic milancurcic merged commit 65b74f8 into fortran-lang:master Oct 1, 2021
@Sideboard Sideboard deleted the feature/gcd branch October 2, 2021 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reviewers needed This patch requires extra eyes topic: mathematics linear algebra, sparse matrices, special functions, FFT, random numbers, statistics, ...
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GCD (Greatest Common Divisior)
8 participants