Skip to content
2 changes: 2 additions & 0 deletions ext/symengine/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
set(RUBY_WRAPPER_SRC
ruby_basic.c
ruby_symbol.c
ruby_number.c
ruby_integer.c
ruby_real_double.c
ruby_real_mpfr.c
ruby_complex.c
ruby_complex_double.c
ruby_complex_mpc.c
ruby_constant.c
ruby_function.c
ruby_ntheory.c
Expand Down
13 changes: 13 additions & 0 deletions ext/symengine/ruby_complex_mpc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "ruby_complex_mpc.h"

#ifdef HAVE_SYMENGINE_MPC
VALUE ccomplex_mpc_real_part(VALUE self)
{
return function_onearg(complex_mpc_real_part, self);
}

VALUE ccomplex_mpc_imaginary_part(VALUE self)
{
return function_onearg(complex_mpc_imaginary_part, self);
}
#endif // HAVE_SYMENGINE_MPC
15 changes: 15 additions & 0 deletions ext/symengine/ruby_complex_mpc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef RUBY_COMPLEX_MPC_H_
#define RUBY_COMPLEX_MPC_H_

#include <ruby.h>
#include <symengine/cwrapper.h>

#include "symengine.h"
#include "symengine_utils.h"

#ifdef HAVE_SYMENGINE_MPC
VALUE ccomplex_mpc_real_part(VALUE self);
VALUE ccomplex_mpc_imaginary_part(VALUE self);
#endif // HAVE_SYMENGINE_MPC

#endif // RUBY_COMPLEX_MPC_H_
50 changes: 50 additions & 0 deletions ext/symengine/ruby_number.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "ruby_number.h"

int cnumber_comp(VALUE self, VALUE operand2)
{
basic cbasic_operand1;
basic cbasic_operand2;
basic_new_stack(cbasic_operand1);
basic_new_stack(cbasic_operand2);

basic cbasic_sub;
basic_new_stack(cbasic_sub);

sympify(self, cbasic_operand1);
sympify(operand2, cbasic_operand2);

Copy link
Member

Choose a reason for hiding this comment

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

You have to check here that cbasic_operand2 is also a Number

if (is_a_Number(cbasic_operand2) == 0) {
rb_raise(rb_eTypeError, "Expected SymEngine::Number found %s ",
rb_obj_classname(operand2));
}

basic_sub(cbasic_sub, cbasic_operand1, cbasic_operand2);

int sign = basic_number_sign(cbasic_sub);

basic_free_stack(cbasic_operand1);
basic_free_stack(cbasic_operand2);
basic_free_stack(cbasic_sub);

return sign;
}

VALUE cnumber_lt(VALUE self, VALUE operand2)
{
return cnumber_comp(self, operand2) == -1 ? Qtrue : Qfalse;
}

VALUE cnumber_gt(VALUE self, VALUE operand2)
{
return cnumber_comp(self, operand2) == 1 ? Qtrue : Qfalse;
}

VALUE cnumber_lt_e(VALUE self, VALUE operand2)
{
return cnumber_comp(self, operand2) == 1 ? Qfalse : Qtrue;
}

VALUE cnumber_gt_e(VALUE self, VALUE operand2)
{
return cnumber_comp(self, operand2) == -1 ? Qfalse : Qtrue;
}
19 changes: 19 additions & 0 deletions ext/symengine/ruby_number.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef RUBY_NUMBER_H_
#define RUBY_NUMBER_H_

#include <ruby.h>
#include <symengine/cwrapper.h>

#include "symengine_utils.h"

int cnumber_comp(VALUE self, VALUE operand2);

VALUE cnumber_lt(VALUE self, VALUE operand2);

VALUE cnumber_gt(VALUE self, VALUE operand2);

VALUE cnumber_lt_e(VALUE self, VALUE operand2);

VALUE cnumber_gt_e(VALUE self, VALUE operand2);

#endif // RUBY_NUMBER_H_
15 changes: 15 additions & 0 deletions ext/symengine/ruby_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,18 @@ VALUE cutils_sympify(VALUE self, VALUE operand)

return result;
}

VALUE cutils_evalf(VALUE self, VALUE operand, VALUE prec, VALUE real)
{
VALUE result;

basic_struct *cresult;
cresult = basic_new_heap();

sympify(operand, cresult);
basic_evalf(cresult, cresult, NUM2INT(prec), (real == Qtrue ? 1 : 0));
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL, cbasic_free_heap,
cresult);

return result;
}
2 changes: 1 addition & 1 deletion ext/symengine/ruby_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

// Returns the Ruby Value after going through sympify
VALUE cutils_sympify(VALUE self, VALUE operand);

VALUE cutils_evalf(VALUE self, VALUE operand, VALUE prec, VALUE real);
#endif // RUBY_UTILS_H_
30 changes: 23 additions & 7 deletions ext/symengine/symengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
#include "ruby_basic.h"
#include "ruby_symbol.h"
#include "ruby_integer.h"
#include "ruby_number.h"
#include "ruby_real_double.h"
#include "ruby_constant.h"
#include "ruby_complex.h"
#include "ruby_complex_double.h"
#include "ruby_complex_mpc.h"
#include "ruby_real_mpfr.h"
#include "ruby_function.h"
#include "ruby_ntheory.h"
Expand Down Expand Up @@ -58,52 +60,66 @@ void Init_symengine()
rb_define_module_function(m_symengine, "convert", cutils_sympify, 1);
rb_define_global_function("SymEngine", cutils_sympify, 1);

// evalf as a Module Level Function
rb_define_module_function(m_symengine, "_evalf", cutils_evalf, 3);

// Symbol class
c_symbol = rb_define_class_under(m_symengine, "Symbol", c_basic);
rb_define_alloc_func(c_symbol, cbasic_alloc);
rb_define_method(c_symbol, "initialize", csymbol_init, 1);

// Number class
c_number = rb_define_class_under(m_symengine, "Number", c_basic);
rb_define_alloc_func(c_number, cbasic_alloc);
rb_define_method(c_number, ">", cnumber_gt, 1);
rb_define_method(c_number, "<", cnumber_lt, 1);
rb_define_method(c_number, ">=", cnumber_gt_e, 1);
rb_define_method(c_number, "<=", cnumber_lt_e, 1);

// Integer class
c_integer = rb_define_class_under(m_symengine, "Integer", c_basic);
c_integer = rb_define_class_under(m_symengine, "Integer", c_number);
rb_define_alloc_func(c_integer, cbasic_alloc);
rb_define_method(c_integer, "initialize", cinteger_init, 1);
rb_define_method(c_integer, "%", cntheory_mod, 1);

// RealDouble Class
c_real_double = rb_define_class_under(m_symengine, "RealDouble", c_basic);
c_real_double = rb_define_class_under(m_symengine, "RealDouble", c_number);
rb_define_alloc_func(c_real_double, cbasic_alloc);
rb_define_method(c_real_double, "to_f", crealdouble_to_float, 0);

// Rational class
c_rational = rb_define_class_under(m_symengine, "Rational", c_basic);
c_rational = rb_define_class_under(m_symengine, "Rational", c_number);
rb_define_alloc_func(c_rational, cbasic_alloc);

// Complex class
c_complex = rb_define_class_under(m_symengine, "Complex", c_basic);
c_complex = rb_define_class_under(m_symengine, "Complex", c_number);
rb_define_alloc_func(c_complex, cbasic_alloc);
rb_define_method(c_complex, "real", ccomplex_real_part, 0);
rb_define_method(c_complex, "imaginary", ccomplex_imaginary_part, 0);

// ComplexDouble class
c_complex_double
= rb_define_class_under(m_symengine, "ComplexDouble", c_basic);
= rb_define_class_under(m_symengine, "ComplexDouble", c_number);
rb_define_alloc_func(c_complex_double, cbasic_alloc);
rb_define_method(c_complex_double, "real", ccomplex_double_real_part, 0);
rb_define_method(c_complex_double, "imaginary",
ccomplex_double_imaginary_part, 0);

#ifdef HAVE_SYMENGINE_MPFR
// RealMPFR class
c_real_mpfr = rb_define_class_under(m_symengine, "RealMPFR", c_basic);
c_real_mpfr = rb_define_class_under(m_symengine, "RealMPFR", c_number);
rb_define_alloc_func(c_real_mpfr, cbasic_alloc);
rb_define_method(c_real_mpfr, "initialize", crealmpfr_init, 2);
rb_define_method(c_real_mpfr, "to_f", crealmpfr_to_float, 0);
#endif // HAVE_SYMENGINE_MPFR

#ifdef HAVE_SYMENGINE_MPC
// ComplexMPC class
c_complex_mpc = rb_define_class_under(m_symengine, "ComplexMPC", c_basic);
c_complex_mpc = rb_define_class_under(m_symengine, "ComplexMPC", c_number);
rb_define_alloc_func(c_complex_mpc, cbasic_alloc);
rb_define_method(c_complex_mpc, "real", ccomplex_mpc_real_part, 0);
rb_define_method(c_complex_mpc, "imaginary", ccomplex_mpc_imaginary_part,
0);
#endif // HAVE_SYMENGINE_MPC

// Constant class
Expand Down
1 change: 1 addition & 0 deletions ext/symengine/symengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ VALUE m_symengine;
// variable names for classes begin with c
VALUE c_basic;
VALUE c_symbol;
VALUE c_number;
VALUE c_integer;
VALUE c_real_double;
VALUE c_rational;
Expand Down
2 changes: 1 addition & 1 deletion ext/symengine/symengine_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void sympify(VALUE operand2, basic_struct *cbasic_operand2)
void get_symintfromval(VALUE operand2, basic_struct *cbasic_operand2)
{
if (TYPE(operand2) == T_FIXNUM) {
int i = NUM2INT(operand2);
long int i = NUM2LONG(operand2);
integer_set_si(cbasic_operand2, i);
} else if (TYPE(operand2) == T_BIGNUM) {
VALUE Rb_Temp_String = rb_funcall(operand2, rb_intern("to_s"), 0, NULL);
Expand Down
5 changes: 4 additions & 1 deletion lib/symengine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ def symbols ary_or_string, *params
end
def Function(n)
return SymEngine::UndefFunction.new(n)
end
end
def evalf(operand, prec=53, real=false)
return _evalf(operand, prec, real)
end
end
end

Expand Down
5 changes: 5 additions & 0 deletions lib/symengine/basic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,10 @@ def inspect
def free_symbols
pr_free_symbols.to_set
end

def abs
return SymEngine::abs(self)
end

end
end
27 changes: 27 additions & 0 deletions spec/evalf_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
describe 'SymEngine::evalf' do
context 'RealDouble values' do
subject { SymEngine::evalf(SymEngine::sin(SymEngine(2)), 53, true) }
it { is_expected.to be_a SymEngine::RealDouble }
it { is_expected.to be_within(1e-15).of(0.909297426825682) }
end
if SymEngine::HAVE_MPFR
context 'RealMPFR values' do
subject { SymEngine::evalf(SymEngine::PI * SymEngine(1963319607) - SymEngine(6167950454), 100, true) }
it { is_expected.to be_a SymEngine::RealMPFR }
it { is_expected.to be_within(SymEngine::RealMPFR.new("1e-41", 100)).of(SymEngine::RealMPFR.new("1.4973429143989597928099399837265e-10", 100)) }
end
end
context 'ComplexDouble values' do
subject { SymEngine::evalf(SymEngine::sin(1) * SymEngine::I, 53, false) }
it { is_expected.to be_a SymEngine::ComplexDouble }
its(:imaginary) { is_expected.to be_within(1e-15).of(0.841470984807897) }
end

if SymEngine::HAVE_MPC
context 'ComplexMPC values' do
subject { SymEngine::evalf(SymEngine::sin(1) * SymEngine::I, 100, false) }
it { is_expected.to be_a SymEngine::ComplexMPC }
its(:imaginary) { is_expected.to be_within(SymEngine::RealMPFR.new("1e-32", 100)).of(SymEngine::RealMPFR.new("0.84147098480789650665250232163005", 100)) }
end
end
end
2 changes: 1 addition & 1 deletion symengine_version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0c17ca9d88f25881c6d0ca382c26b2eb392b9b48
bb18f1c1f4cbc29765fe1bcbd2dbe9345279b659