diff --git a/ext/symengine/ruby_utils.c b/ext/symengine/ruby_utils.c index 7fc948a..b2dc67b 100644 --- a/ext/symengine/ruby_utils.c +++ b/ext/symengine/ruby_utils.c @@ -11,7 +11,24 @@ VALUE cutils_sympify(VALUE self, VALUE operand) sympify(operand, cbasic_operand); result = Data_Wrap_Struct(Klass_of_Basic(cbasic_operand), NULL, cbasic_free_heap, cbasic_operand); + return result; +} + +VALUE cutils_parse(VALUE self, VALUE str) +{ + VALUE result = Qnil; + basic_struct *cbasic_result = basic_new_heap(); + + char *cstr = RSTRING_PTR(str); + symengine_exceptions_t error_code = basic_parse(cbasic_result, cstr); + + if (error_code == SYMENGINE_NO_EXCEPTION) { + result = Data_Wrap_Struct(Klass_of_Basic(cbasic_result), NULL, + cbasic_free_heap, cbasic_result); + } else { + raise_exception(error_code); + } return result; } @@ -23,6 +40,7 @@ VALUE cutils_evalf(VALUE self, VALUE operand, VALUE prec, VALUE real) cresult = basic_new_heap(); sympify(operand, cresult); + symengine_exceptions_t error_code = basic_evalf(cresult, cresult, NUM2INT(prec), (real == Qtrue ? 1 : 0)); diff --git a/ext/symengine/ruby_utils.h b/ext/symengine/ruby_utils.h index 65edbf2..1d39932 100644 --- a/ext/symengine/ruby_utils.h +++ b/ext/symengine/ruby_utils.h @@ -5,5 +5,9 @@ // Returns the Ruby Value after going through sympify VALUE cutils_sympify(VALUE self, VALUE operand); +// Parses the expression in str and returns a SymEngine::Basic +VALUE cutils_parse(VALUE self, VALUE str); +// Evaluates the numerical value in operand (SymEngine::Basic) to precision +// defined in prec VALUE cutils_evalf(VALUE self, VALUE operand, VALUE prec, VALUE real); #endif // RUBY_UTILS_H_ diff --git a/ext/symengine/symengine.c b/ext/symengine/symengine.c index 11af6a9..90a9162 100644 --- a/ext/symengine/symengine.c +++ b/ext/symengine/symengine.c @@ -60,6 +60,9 @@ void Init_symengine() rb_define_module_function(m_symengine, "convert", cutils_sympify, 1); rb_define_global_function("SymEngine", cutils_sympify, 1); + // Parser as a Module Level Function + rb_define_module_function(m_symengine, "parse", cutils_parse, 1); + // evalf as a Module Level Function rb_define_module_function(m_symengine, "_evalf", cutils_evalf, 3); diff --git a/spec/symengine_spec.rb b/spec/symengine_spec.rb index 0f1017a..306ef52 100644 --- a/spec/symengine_spec.rb +++ b/spec/symengine_spec.rb @@ -18,5 +18,52 @@ it { is_expected.to be_a SymEngine::Rational } its(:to_s) { is_expected.to eq '1/3' } end + + describe 'parse' do + subject { SymEngine::parse('123 + 321') } + + it { is_expected.to be_a SymEngine::Integer } + it { is_expected.to eq 444 } + end + + it 'gives parse errors' do + expect { SymEngine::parse('12a + n34a9') }.to raise_error(RuntimeError) + end + + describe 'parse an Add' do + subject { SymEngine::parse('x + (y * 3 - 5)') } + + it { is_expected.to be_a SymEngine::Add } + end + + describe 'parse a Pow' do + subject { SymEngine::parse('x ** y') } + + it { is_expected.to be_a SymEngine::Pow } + end + + describe 'parse rational values' do + subject { SymEngine::parse('1 / 3 + 3 / 2') } + + it { is_expected.to eq SymEngine(11)/SymEngine(6) } + end + + describe 'parse integer expressions' do + subject { SymEngine::parse('1 + 2 * 2') } + + it { is_expected.to eq 5 } + end + + describe 'parse trig functions' do + subject { SymEngine::parse('sin(x) + cos(y) / 2') } + + it { is_expected.to be_a SymEngine::Add } + end + + describe 'parse functions' do + subject { SymEngine::parse('tan(0) - sqrt(2)') } + + it { is_expected.to be_a SymEngine::Mul } + end end