From e8a5670eff8e1d38bb7e32aad17fb8d2f74cebe8 Mon Sep 17 00:00:00 2001 From: rajithv Date: Thu, 9 Jun 2016 09:43:19 +0530 Subject: [PATCH 01/12] FunctionSymbol class and its methods --- ext/symengine/ruby_function.c | 28 ++++++++++++++++++++++++++++ ext/symengine/ruby_function.h | 2 ++ ext/symengine/symengine.c | 6 ++++-- ext/symengine/symengine.h | 1 + ext/symengine/symengine_utils.c | 2 ++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ext/symengine/ruby_function.c b/ext/symengine/ruby_function.c index e8be33a..e92c4b3 100644 --- a/ext/symengine/ruby_function.c +++ b/ext/symengine/ruby_function.c @@ -37,3 +37,31 @@ IMPLEMENT_ONE_ARG_FUNC(gamma); #undef IMPLEMENT_ONE_ARG_FUNC +VALUE cfunction_functionsymbol_init(VALUE self, VALUE args) +{ + int argc = NUM2INT(rb_funcall(args, rb_intern("length"), 0, NULL)); + printf("%d\n", argc); + VALUE first = rb_ary_shift(args); + if( TYPE(first) != T_STRING ){ + rb_raise(rb_eTypeError, "String expected as first argument"); + } + char *name = StringValueCStr( first ); + + basic_struct *cargs[argc]; + int i; + for(i = 0; i < argc; i++){ + cargs[i] = basic_new_heap(); + sympify(rb_ary_shift(args), cargs[i]); + } + + basic_struct *this; + Data_Get_Struct(self, basic_struct, this); + + function_symbol_set(this, name, cargs); + + for(i = 0; i < argc; i++){ + basic_free_heap(cargs[i]); + } + return self; +} + diff --git a/ext/symengine/ruby_function.h b/ext/symengine/ruby_function.h index e55b63b..b271353 100644 --- a/ext/symengine/ruby_function.h +++ b/ext/symengine/ruby_function.h @@ -37,4 +37,6 @@ VALUE cfunction_dirichlet_eta(VALUE self, VALUE operand1); VALUE cfunction_zeta(VALUE self, VALUE operand1); VALUE cfunction_gamma(VALUE self, VALUE operand1); +VALUE cfunction_functionsymbol_init(VALUE self, VALUE args); + #endif //RUBY_FUNCTION_H_ diff --git a/ext/symengine/symengine.c b/ext/symengine/symengine.c index 8ca3d36..1be6f58 100644 --- a/ext/symengine/symengine.c +++ b/ext/symengine/symengine.c @@ -113,10 +113,12 @@ void Init_symengine() { c_dirichlet_eta = rb_define_class_under(m_symengine, "Dirichlet_eta", c_function); c_zeta = rb_define_class_under(m_symengine, "Zeta", c_function); c_gamma = rb_define_class_under(m_symengine, "Gamma", c_function); - - //Abs Class c_abs = rb_define_class_under(m_symengine, "Abs", c_function); + //FunctionSymbol Class + c_function_symbol = rb_define_class_under(m_symengine, "FunctionSymbol", c_function); + rb_define_method(c_function_symbol, "initialize", cfunction_functionsymbol_init, -2); + //TrigFunction SubClasses c_sin = rb_define_class_under(m_symengine, "Sin", c_trig_function); c_cos = rb_define_class_under(m_symengine, "Cos", c_trig_function); diff --git a/ext/symengine/symengine.h b/ext/symengine/symengine.h index 21259a6..0ac1e03 100644 --- a/ext/symengine/symengine.h +++ b/ext/symengine/symengine.h @@ -19,6 +19,7 @@ VALUE c_add; VALUE c_mul; VALUE c_pow; VALUE c_function; +VALUE c_function_symbol; VALUE c_trig_function; VALUE c_hyperbolic_function; VALUE c_lambertw; diff --git a/ext/symengine/symengine_utils.c b/ext/symengine/symengine_utils.c index a3ccbf1..418ecca 100644 --- a/ext/symengine/symengine_utils.c +++ b/ext/symengine/symengine_utils.c @@ -101,6 +101,8 @@ VALUE Klass_of_Basic(const basic_struct *basic_ptr) { return c_mul; case SYMENGINE_POW: return c_pow; + case SYMENGINE_FUNCTIONSYMBOL: + return c_function_symbol; case SYMENGINE_ABS: return c_abs; case SYMENGINE_SIN: From b5a91fd12c2a0b5aac1ec440a249082aa1241d88 Mon Sep 17 00:00:00 2001 From: rajithv Date: Thu, 9 Jun 2016 15:37:03 +0530 Subject: [PATCH 02/12] FunctionSymbol init working --- ext/symengine/ruby_function.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/ext/symengine/ruby_function.c b/ext/symengine/ruby_function.c index e92c4b3..1f0537f 100644 --- a/ext/symengine/ruby_function.c +++ b/ext/symengine/ruby_function.c @@ -1,5 +1,7 @@ #include "ruby_function.h" +typedef struct CVecBasic CVecBasic; + #define IMPLEMENT_ONE_ARG_FUNC(func) \ VALUE cfunction_ ## func(VALUE self, VALUE operand1) { \ return function_onearg(basic_ ## func, operand1); \ @@ -40,28 +42,36 @@ IMPLEMENT_ONE_ARG_FUNC(gamma); VALUE cfunction_functionsymbol_init(VALUE self, VALUE args) { int argc = NUM2INT(rb_funcall(args, rb_intern("length"), 0, NULL)); - printf("%d\n", argc); + printf("argc : %d\n", argc); VALUE first = rb_ary_shift(args); if( TYPE(first) != T_STRING ){ rb_raise(rb_eTypeError, "String expected as first argument"); } char *name = StringValueCStr( first ); + char *c; + + CVecBasic *cargs = vecbasic_new(); + + //basic_struct *cargs[argc]; - basic_struct *cargs[argc]; + basic x; + basic y; + basic_new_stack(x); int i; - for(i = 0; i < argc; i++){ - cargs[i] = basic_new_heap(); - sympify(rb_ary_shift(args), cargs[i]); + for(i = 0; i < argc-1; i++){ + printf("%d : ", i); + sympify(rb_ary_shift(args), x); + vecbasic_push_back(cargs, x); } + + basic_free_stack(x); basic_struct *this; Data_Get_Struct(self, basic_struct, this); function_symbol_set(this, name, cargs); - for(i = 0; i < argc; i++){ - basic_free_heap(cargs[i]); - } + vecbasic_free(cargs); return self; } From 2dd2966428dda01857a370922af69761220c91e8 Mon Sep 17 00:00:00 2001 From: rajithv Date: Thu, 9 Jun 2016 19:52:14 +0530 Subject: [PATCH 03/12] Removed commented code and print statements. Added an error for no arguments --- ext/symengine/ruby_function.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/ext/symengine/ruby_function.c b/ext/symengine/ruby_function.c index 1f0537f..1f16bd7 100644 --- a/ext/symengine/ruby_function.c +++ b/ext/symengine/ruby_function.c @@ -41,37 +41,34 @@ IMPLEMENT_ONE_ARG_FUNC(gamma); VALUE cfunction_functionsymbol_init(VALUE self, VALUE args) { - int argc = NUM2INT(rb_funcall(args, rb_intern("length"), 0, NULL)); - printf("argc : %d\n", argc); + int argc = NUM2INT(rb_ary_length(args)); + if(argc == 0){ + rb_raise(rb_eTypeError, "Arguments Expected"); + } + VALUE first = rb_ary_shift(args); if( TYPE(first) != T_STRING ){ rb_raise(rb_eTypeError, "String expected as first argument"); } - char *name = StringValueCStr( first ); - char *c; + char *name = StringValueCStr(first); CVecBasic *cargs = vecbasic_new(); - //basic_struct *cargs[argc]; - basic x; - basic y; basic_new_stack(x); int i; for(i = 0; i < argc-1; i++){ - printf("%d : ", i); sympify(rb_ary_shift(args), x); vecbasic_push_back(cargs, x); } - - basic_free_stack(x); basic_struct *this; Data_Get_Struct(self, basic_struct, this); - function_symbol_set(this, name, cargs); vecbasic_free(cargs); + basic_free_stack(x); + return self; } From 0e92c92bde6f8218d3c4a22be22110501bc5ae82 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Fri, 10 Jun 2016 20:56:15 +0530 Subject: [PATCH 04/12] Changed rb_ary_length to RARRAY_LEN --- ext/symengine/ruby_function.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/symengine/ruby_function.c b/ext/symengine/ruby_function.c index 1f16bd7..e33de98 100644 --- a/ext/symengine/ruby_function.c +++ b/ext/symengine/ruby_function.c @@ -41,7 +41,7 @@ IMPLEMENT_ONE_ARG_FUNC(gamma); VALUE cfunction_functionsymbol_init(VALUE self, VALUE args) { - int argc = NUM2INT(rb_ary_length(args)); + int argc = RARRAY_LEN(args); if(argc == 0){ rb_raise(rb_eTypeError, "Arguments Expected"); } From e38cf80833b1eb109a684fe4f3c0821490df2c76 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Fri, 10 Jun 2016 21:01:42 +0530 Subject: [PATCH 05/12] Added Subs class --- ext/symengine/symengine.c | 3 +++ ext/symengine/symengine.h | 1 + ext/symengine/symengine_utils.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ext/symengine/symengine.c b/ext/symengine/symengine.c index 1be6f58..4b3bb02 100644 --- a/ext/symengine/symengine.c +++ b/ext/symengine/symengine.c @@ -93,6 +93,9 @@ void Init_symengine() { rb_define_const(m_symengine, "E", cconstant_e()); rb_define_const(m_symengine, "EULER_GAMMA", cconstant_euler_gamma()); rb_define_const(m_symengine, "I", cconstant_i()); + + //Subs class + c_subs = rb_define_class_under(m_symengine, "Subs", c_basic); //Add class c_add = rb_define_class_under(m_symengine, "Add", c_basic); diff --git a/ext/symengine/symengine.h b/ext/symengine/symengine.h index 0ac1e03..dd9d387 100644 --- a/ext/symengine/symengine.h +++ b/ext/symengine/symengine.h @@ -15,6 +15,7 @@ VALUE c_rational; VALUE c_complex; VALUE c_complex_double; VALUE c_constant; +VALUE c_subs; VALUE c_add; VALUE c_mul; VALUE c_pow; diff --git a/ext/symengine/symengine_utils.c b/ext/symengine/symengine_utils.c index 418ecca..eac0df0 100644 --- a/ext/symengine/symengine_utils.c +++ b/ext/symengine/symengine_utils.c @@ -95,6 +95,8 @@ VALUE Klass_of_Basic(const basic_struct *basic_ptr) { return c_complex_double; case SYMENGINE_CONSTANT: return c_constant; + case SYMENGINE_SUBS: + return c_subs; case SYMENGINE_ADD: return c_add; case SYMENGINE_MUL: From 310b7bf03b4e2d856150a088072f1e75ce29d537 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Fri, 10 Jun 2016 21:51:14 +0530 Subject: [PATCH 06/12] Added specs for FunctionSymbol --- spec/function_symbol_spec.rb | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 spec/function_symbol_spec.rb diff --git a/spec/function_symbol_spec.rb b/spec/function_symbol_spec.rb new file mode 100644 index 0000000..233ef53 --- /dev/null +++ b/spec/function_symbol_spec.rb @@ -0,0 +1,33 @@ +describe SymEngine::FunctionSymbol do + + let(:x) { sym('x') } + let(:y) { sym('y') } + let(:z) { sym('z') } + + describe '.new' do + context 'with symbols' do + subject { SymEngine::FunctionSymbol.new('f', x, y, z) } + it { is_expected.to be_a SymEngine::FunctionSymbol } + end + + context 'with compound arguments' do + subject { SymEngine::FunctionSymbol.new('f', 2*x, y, SymEngine::sin(z)) } + it { is_expected.to be_a SymEngine::FunctionSymbol } + end + end + + context '#diff' do + let(:fun) { (SymEngine::FunctionSymbol.new('f', 2*x, y, SymEngine::sin(z))) } + context 'by variable' do + subject { fun.diff(x)/2 } + it { is_expected.to be_a SymEngine::Subs } + end + + context 'by constant' do + subject { fun.diff(2) } + it { is_expected.to be_nil } + end + end +end + + From 4c538accd45bca47526582ff211cfe329a9f1f96 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Fri, 10 Jun 2016 21:54:07 +0530 Subject: [PATCH 07/12] SymEngine version changed --- symengine_version.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/symengine_version.txt b/symengine_version.txt index 7c04801..c5bccf3 100644 --- a/symengine_version.txt +++ b/symengine_version.txt @@ -1,2 +1,3 @@ -b91c64a3b82f15133f4a7df64749523bb0bed185 +1d80d81096b66c08ad3fe4e43ee586cd91b5ccf8 + From ceeb75737b8c92e22522f28865ba897a5cfee1a6 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Sun, 12 Jun 2016 01:07:07 +0530 Subject: [PATCH 08/12] Formatting Corrections --- ext/symengine/ruby_function.c | 6 +++--- symengine_version.txt | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ext/symengine/ruby_function.c b/ext/symengine/ruby_function.c index e33de98..017a8b7 100644 --- a/ext/symengine/ruby_function.c +++ b/ext/symengine/ruby_function.c @@ -42,12 +42,12 @@ IMPLEMENT_ONE_ARG_FUNC(gamma); VALUE cfunction_functionsymbol_init(VALUE self, VALUE args) { int argc = RARRAY_LEN(args); - if(argc == 0){ + if (argc == 0) { rb_raise(rb_eTypeError, "Arguments Expected"); } VALUE first = rb_ary_shift(args); - if( TYPE(first) != T_STRING ){ + if (TYPE(first) != T_STRING) { rb_raise(rb_eTypeError, "String expected as first argument"); } char *name = StringValueCStr(first); @@ -57,7 +57,7 @@ VALUE cfunction_functionsymbol_init(VALUE self, VALUE args) basic x; basic_new_stack(x); int i; - for(i = 0; i < argc-1; i++){ + for (i = 0; i < argc-1; i++) { sympify(rb_ary_shift(args), x); vecbasic_push_back(cargs, x); } diff --git a/symengine_version.txt b/symengine_version.txt index c5bccf3..8c84fb4 100644 --- a/symengine_version.txt +++ b/symengine_version.txt @@ -1,3 +1 @@ 1d80d81096b66c08ad3fe4e43ee586cd91b5ccf8 - - From 91b414b075fe1be2d92d22195f805cf5ad5091ce Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Sun, 12 Jun 2016 23:59:02 +0530 Subject: [PATCH 09/12] Fixing the function_symbol_spec.rb --- spec/function_symbol_spec.rb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/spec/function_symbol_spec.rb b/spec/function_symbol_spec.rb index 233ef53..47cc0d5 100644 --- a/spec/function_symbol_spec.rb +++ b/spec/function_symbol_spec.rb @@ -19,14 +19,9 @@ context '#diff' do let(:fun) { (SymEngine::FunctionSymbol.new('f', 2*x, y, SymEngine::sin(z))) } context 'by variable' do - subject { fun.diff(x)/2 } - it { is_expected.to be_a SymEngine::Subs } - end - - context 'by constant' do - subject { fun.diff(2) } - it { is_expected.to be_nil } - end + subject { fun.diff(x)/2 } + it { is_expected.to be_a SymEngine::Subs } + end end end From 8932ada3a748c7e02f0035a66c15e16b2586fdd3 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Mon, 13 Jun 2016 16:19:36 +0530 Subject: [PATCH 10/12] UndefFunction --- ext/symengine/symengine_utils.c | 3 +-- lib/symengine.rb | 6 +++++- lib/symengine/undef_function.rb | 13 +++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 lib/symengine/undef_function.rb diff --git a/ext/symengine/symengine_utils.c b/ext/symengine/symengine_utils.c index fa24842..e4385f1 100644 --- a/ext/symengine/symengine_utils.c +++ b/ext/symengine/symengine_utils.c @@ -8,7 +8,6 @@ void sympify(VALUE operand2, basic_struct *cbasic_operand2) { VALUE a, b; double f; char *c; - rb_cBigDecimal = CLASS_OF(rb_eval_string("BigDecimal.new('0.0001')")); switch(TYPE(operand2)) { case T_FIXNUM: @@ -63,7 +62,7 @@ void sympify(VALUE operand2, basic_struct *cbasic_operand2) { case T_DATA: c = rb_obj_classname(operand2); #ifdef HAVE_SYMENGINE_MPFR - if(CLASS_OF(operand2) == rb_cBigDecimal){ + if (strcmp(c, "BigDecimal") == 0) { c = RSTRING_PTR( rb_funcall(operand2, rb_intern("to_s"), 1, rb_str_new2("F")) ); real_mpfr_set_str(cbasic_operand2, c, 200); break; diff --git a/lib/symengine.rb b/lib/symengine.rb index 21d4c7d..36c8806 100644 --- a/lib/symengine.rb +++ b/lib/symengine.rb @@ -1,6 +1,5 @@ module SymEngine class << self - # Defines a shortcut for SymEngine::Symbol.new() allowing multiple symbols # to be created all at once. # @@ -29,6 +28,10 @@ def symbols ary_or_string, *params end end end + + def SymEngine.Function(n) + return SymEngine::UndefFunction.new(n) + end end require 'symengine/symengine' @@ -37,3 +40,4 @@ def symbols ary_or_string, *params require 'symengine/integer' require 'symengine/complex' require 'symengine/complex_double' +require 'symengine/undef_function' diff --git a/lib/symengine/undef_function.rb b/lib/symengine/undef_function.rb new file mode 100644 index 0000000..8982b8b --- /dev/null +++ b/lib/symengine/undef_function.rb @@ -0,0 +1,13 @@ +module SymEngine + class UndefFunction + + def initialize(n) + @name = n + end + + def call(*args) + SymEngine::FunctionSymbol.new(@name, *args) + end + + end +end From 8a298f030733d080c989c73a7cfb659935182e2e Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Mon, 13 Jun 2016 22:40:45 +0530 Subject: [PATCH 11/12] Moving Function() inside SymEngine module's self class --- lib/symengine.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/symengine.rb b/lib/symengine.rb index 36c8806..e4d3477 100644 --- a/lib/symengine.rb +++ b/lib/symengine.rb @@ -26,11 +26,10 @@ def symbols ary_or_string, *params ary_or_string.map do |symbol_or_string| SymEngine::Symbol.new(symbol_or_string) end - end - end - - def SymEngine.Function(n) - return SymEngine::UndefFunction.new(n) + end + def Function(n) + return SymEngine::UndefFunction.new(n) + end end end From 6c0fe5dba124cb328abd4db8b87dc973e52f2403 Mon Sep 17 00:00:00 2001 From: Rajith Vidanaarachchi Date: Mon, 13 Jun 2016 22:58:00 +0530 Subject: [PATCH 12/12] Spec for UndefFunction and it's call method --- spec/function_symbol_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/function_symbol_spec.rb b/spec/function_symbol_spec.rb index 47cc0d5..f73d2eb 100644 --- a/spec/function_symbol_spec.rb +++ b/spec/function_symbol_spec.rb @@ -23,6 +23,18 @@ it { is_expected.to be_a SymEngine::Subs } end end + + context 'Initializing with UndefFunctions' do + let(:fun) { SymEngine::Function('f') } + context 'UndefFunction' do + subject { fun } + it { is_expected.to be_a SymEngine::UndefFunction } + end + context 'using call method for UndefFunction' do + subject { fun.(x, y, z) } + it { is_expected.to be_a SymEngine::FunctionSymbol } + end + end end