-
Notifications
You must be signed in to change notification settings - Fork 15
Ruby Wrappers for NTheory #38
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
Conversation
| VALUE result; | ||
|
|
||
| unsigned long cbasic_operand1; | ||
| cbasic_operand1 = NUM2ULONG(operand1); |
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.
@abinashmeher999 am I using this correctly? Pls check.
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, that is correct. If you get unsure about return types, refer here: http://rxr.whitequark.org/mri/ident
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.
Then all you need to do is to add an implicit conversion of SymEngine::Integer into Integer
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 figured our half way on how to do this:
so I added a new method to the 'Integer' class
rb_define_method(c_integer, "to_int", cinteger_to_int, 0);
From which I should return a VALUE pointer pointing to a Ruby Bignum or a Fixnum. This can be done by converting a C int by using INT2NUM macro.
The step I'm stuck at is on extracting a C int from the SymEngine Integer object. @abinashmeher999 can you point me to somewhere I can read more about the Ruby Wrapper's SymEngine Integer's structure?
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.
@rajithv, the Integer object uses GMP underneath. So you can extract a gmp int easily using the as_mpz() method. If you want an integer, you can call as_int(), but it will raise an exception if the integer doesn't fit into signed long int.
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.
You can convert a SymEngine::Integer to a Ruby string first and then call to_i method
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.
+1. This can be done. So instead of using the Ruby C API for the above, you can define #to_int in ruby itself here. Make a new file integer.rb and then proceed.
| end | ||
|
|
||
| describe '#mod' do | ||
| context '5 mod 4' 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.
Also add tests for other permutations of a positive and a negative number and see if they behave the same way as ruby, because I have heard they do not behave the same way in python and C.
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.
@abinashmeher999 The same happens in Ruby. So I should adapt the code to return Ruby-like answers. right?
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.
IMHO symengine's behavior should be consistent across all languages. But again there shouldn't be any surprises for ruby users. If both are same then it's good.
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 agree with the 2nd not the 1st point.
There are two versions, mod and mod_f and they are used in C++ and Python respectively. You want the mod_f version for Ruby
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 modified the ruby wrapper to return the same as mod_f.
But should I go ahead and wrap mod_f in SymEngine, and get that to the ruby wrapper? Or is it not necessary?
Also, should there be a way to access the c-style mod operation in Ruby?
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'll be better to have the mod_f function in SymEngine. For now, that's okay. You can open an issue to keep track of it.
|
@abinashmeher999 @isuruf good to merge? |
ext/symengine/ruby_ntheory.h
Outdated
| #include "symengine_utils.h" | ||
|
|
||
| VALUE cntheory_onearg(void (*cwfunc_ptr)(basic_struct*, const basic_struct*), VALUE operand1); | ||
| VALUE cntheory_twoarg(void (*cwfunc_ptr)(basic_struct*, const basic_struct*, const basic_struct*), VALUE operand1, VALUE operand2); |
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.
Please break this one too.
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's actually not needed. Removed it.
|
Let's wait for the tests to pass. |
spec/ntheory_spec.rb
Outdated
| describe '#mod' do | ||
| context '5 mod 4' do | ||
| it 'returns 1' do | ||
| f = SymEngine::mod(5, 4) |
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 should use ruby's % operator
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.
So I should overload % right? not introduce a new method as mod.
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.
spec/ntheory_spec.rb
Outdated
| context '5 mod 4' do | ||
| it 'returns 1' do | ||
| f = SymEngine::mod(5, 4) | ||
| f = 5 % 4 |
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.
You are testing ruby's in built ints here
|
@abinashmeher999 @isuruf pls review. |
| describe '#fibonacci' do | ||
| context '5th Fibonacci Number' do | ||
| it 'returns 5' do | ||
| f = SymEngine::fibonacci(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.
You should add another test which uses a SymEngine integer instead of Ruby's
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.
Better to add it to all of them. Or at least one for one argument and one for two argument function.
|
@isuruf @abinashmeher999 done |
| context '-5 mod 4' do | ||
| it 'returns 3' do | ||
| f = @im5 % @i4 | ||
| expect(f).to eql(3) |
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.
So, f is a SymEngine::Integer, right? Will implicit conversion happen here while comparing?
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 just found eql checks hash equality and type conversions are taken care in eq.
| expect(f).to eql(5) | ||
| end | ||
| end | ||
| context 'binomial (n=5, k=1)' 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.
Make the wording of the context like with SymEngine::Integer as parameters and same for the test above this with ruby Integer as parameters. This is easier to read when tests are run in verbose mode. Currently it will print
#binomial
binomial (n=5, k=1)
returns 5
binomial (n=5, k=1)
returns 5
Accordingly modify it string. If the tests pass please make sure to make these changes in a new PR.
|
@rajithv Thanks for the PR and your patience. +1 to merge. The minor changes can be incorporated in another PR. |
No description provided.