-
Notifications
You must be signed in to change notification settings - Fork 15
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
Matrix Ruby Wrappers #56
base: master
Are you sure you want to change the base?
Conversation
VALUE cmatrix_dense_alloc(VALUE klass) | ||
{ | ||
CDenseMatrix *mat_ptr = dense_matrix_new(); | ||
return Data_Wrap_Struct(klass, NULL, cmatrix_dense_free, mat_ptr); |
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 does klass
stand for here?
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 was writing it by taking the example of cbasic_alloc. So assumed, the klass is something which is called when allocating the space bound defined in rb_define_alloc_func(c_dense_matrix, cmatrix_dense_alloc);
Shoud I remove it?
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.
klass
is the class object. https://github.com/symengine/symengine.rb/blob/master/ext/symengine/ruby_basic.h#L13
Please check the following:
The |
There are two main things to consider:
v = Daru::DataFrame.new(a: [1,2,3], b: [4,5,6])
# => #<Daru::DataFrame(3x2)>
# a b
# 0 1 4
# 1 2 5
# 2 3 6
v = Daru::DataFrame.new(a: (1..100), b: (201..300))
# => #<Daru::DataFrame(100x2)>
# a b
# 0 1 201
# 1 2 202
# 2 3 203
# 3 4 204
# 4 5 205
# 5 6 206
# 6 7 207
# 7 8 208
# 8 9 209
# 9 10 210
# 10 11 211
# 11 12 212
# 12 13 213
# 13 14 214
# 14 15 215
# ... ... ...
# ^ above is full output of #inspect of large DataFrame, including those "..."
|
|
||
} else if (argc == 2) { | ||
|
||
// SymEngine::DenseMatrix(no_rows, no_cols) |
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 is needed in C++ layer, but not needed in Ruby 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.
@isuruf should I remove it?
I suppose this can be used to generate an empty Matrix of size RxC, where individual elements can be assigned with set
. But again, there's no point in doing that.
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, for that use case, it's better to use zeros
@isuruf @abinashmeher999 @zverok ready for review. @zverok I'm not too sure about the specs. Please advice if I'm not doing it right :) |
Looking at it! |
@@ -0,0 +1,7 @@ | |||
module SymEngine | |||
class MatrixBase |
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.
Shouldn't it say class DenseMatrix
here?
I've left some comments. |
@@ -66,35 +66,6 @@ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"or create a variable" |
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.
Can you remove these changes from this PR?
VALUE operand = rb_ary_shift(args); | ||
char *s = rb_obj_classname(operand); | ||
|
||
if (strcmp(s, "SymEngine::DenseMatrix") == 0) { |
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 move this if else
function to a new function, sympify_matrix
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 use a C API call to check that operand
is a DenseMatrix
instead of string comparisons
expect(matA.rows). to eq (3) | ||
expect(matA.cols). to eq (3) | ||
end | ||
end |
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 think, you can completely omit those describe
s including only one example each, it
s texts are pretty informative and well-written 👍
Just less cognitive load would be to read it this way:
describe SymEngine::DenseMatrix do
describe 'convert' do
subject { SymEngine([[1, 2],[3, 4]]) }
it { is_expected.to be_a SymEngine::DenseMatrix }
its(:to_s) { is_expected.to eq "[1, 2]\n[3, 4]\n" }
end
describe 'methods without arguments' do # that descibes accurately why you group it
subject { SymEngine([[4, 3],[3, 2]]) }
# moving those two here as they are pretty basic & have no arguments
its(:rows) { is_expected.to eq (2) }
its(:cols) { is_expected.to eq (2) }
its(:inv) { is_expected.to be_a SymEngine::DenseMatrix }
its(:inv) { is_expected.to eq SymEngine([[-2, 3],[3, -4]]) }
its(:FFLU) { is_expected.to be_a SymEngine::DenseMatrix }
its(:FFLU) { is_expected.to eq SymEngine([[4, 3],[3, -1]]) }
its(:LU) { is_expected.to eq [SymEngine([[1, 0],[SymEngine(3)/SymEngine(4), 1]]),
SymEngine([[4, 3],[0, SymEngine(-1)/SymEngine(4)]])] }
its(:LDL) { is_expected.to eq [SymEngine([[1, 0],[SymEngine(3)/SymEngine(4), 1]]),
SymEngine([[4, 0],[0, SymEngine(-1)/SymEngine(4)]])] }
its(:FFLDU) { is_expected.to eq [SymEngine([[4, 0],[3, 1]]), SymEngine([[4, 0],[0, 4]]),
SymEngine([[4, 3],[0, -1]])] }
its(:det) { is_expected.to eq (-1)}
end
describe 'methods with arguments' do
let(:mat1) { SymEngine([[1, 2],[3, 4]]) }
let(:mat2) { SymEngine([[4, 3],[2, 1]]) }
let(:a) { SymEngine(4) }
let(:matA) { SymEngine([[3, 1, 2],[5, 7, 5], [1, 2, 3]]) }
let(:b) { SymEngine([[4],[4],[4]]) }
it 'adds and multiplies' do
expect(mat1 + mat2).to eq(SymEngine([[5, 5],[5, 5]]))
expect(mat1 + a).to eq(SymEngine([[5, 6],[7, 8]]))
expect(mat1 * mat2).to eq(SymEngine([[8, 5],[20, 13]]))
expect(mat1 * a).to eq(SymEngine([[4, 8],[12, 16]]))
end
it 'performs transpose and submatrix' do
expect(mat1.transpose).to eq(SymEngine([[1, 3],[2, 4]]))
expect(mat1.submatrix(0, 0, 1, 0, 1, 1)).to eq(SymEngine([[1],[3]]))
end
it 'solves Ax = b' do
expect(matA.LU_solve(b)).to eq(SymEngine([[SymEngine(12)/SymEngine(29)],
[SymEngine(-32)/SymEngine(29)],
[SymEngine(56)/SymEngine(29)]
]))
end
it 'gets and sets elements' do
expect(mat1.set(0, 0, a)).to eq(SymEngine([[4, 2],[3, 4]]))
expect(mat1.get(1, 0)).to eq(SymEngine(3))
end
end
end
WDYT?
No description provided.