From 4a8ef93786f697ca122aeafe2088d6bdffe512db Mon Sep 17 00:00:00 2001 From: Vaibhav Yenamandra Date: Wed, 15 Jun 2016 10:02:36 +0530 Subject: [PATCH] Add ability to assign ruby complex types to GSL::Matrix::Complex (#38) * * Added a case for `T_COMPLEX` in rb_gsl_complex_new(1..2) and rb_gsl_obj_to_gsl_complex(1) * Currently the ops on `::Complex` number is handled via rb_funcall(2..) * Added a test for creating `GSL::Complex` by passing `Complex ` type to `GSL::Complex#alloc` * There is an added cost due to the call to rb_funcall(2..) being used since the @real, @image ivars appear to be unset, in addition to this, struct RComplex is not publicly exposed and to use TypedData_Get_Struct(3) this struct would need to be replicated along with all its dependants. * Fixed a typo that led to failing tests --- ext/gsl_native/complex.c | 12 +++++++++++- test/gsl/complex_test.rb | 13 ++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ext/gsl_native/complex.c b/ext/gsl_native/complex.c index 40b1ac5e..a637787d 100644 --- a/ext/gsl_native/complex.c +++ b/ext/gsl_native/complex.c @@ -41,6 +41,11 @@ gsl_complex rb_gsl_obj_to_gsl_complex(VALUE obj, gsl_complex *z) if (!NIL_P(vre)) GSL_SET_REAL(z, NUM2DBL(vre)); if (!NIL_P(vim)) GSL_SET_IMAG(z, NUM2DBL(vim)); break; + case T_COMPLEX: + vre = rb_funcall(obj, rb_intern("real"), 0); + vim = rb_funcall(obj, rb_intern("imag"), 0); + *z = gsl_complex_rect(NUM2DBL(vre), NUM2DBL(vim)); + break; case T_FLOAT: case T_FIXNUM: case T_BIGNUM: @@ -63,7 +68,7 @@ gsl_complex rb_gsl_obj_to_gsl_complex(VALUE obj, gsl_complex *z) static VALUE rb_gsl_complex_new(int argc, VALUE *argv, VALUE klass) { gsl_complex *c = NULL; - VALUE obj; + VALUE obj, vre, vim; obj = Data_Make_Struct(klass, gsl_complex, 0, free, c); switch (argc) { case 1: @@ -71,6 +76,11 @@ static VALUE rb_gsl_complex_new(int argc, VALUE *argv, VALUE klass) case T_ARRAY: *c = ary2complex(argv[0]); break; + case T_COMPLEX: + vre = rb_funcall(argv[0], rb_intern("real"), 0); + vim = rb_funcall(argv[0], rb_intern("imag"), 0); + *c = gsl_complex_rect(NUM2DBL(vre), NUM2DBL(vim)); + break; case T_FLOAT: case T_FIXNUM: case T_BIGNUM: diff --git a/test/gsl/complex_test.rb b/test/gsl/complex_test.rb index 07e996e4..a1a01167 100644 --- a/test/gsl/complex_test.rb +++ b/test/gsl/complex_test.rb @@ -16,5 +16,16 @@ def test_complex 'gsl_complex_polar imag part at (r=%g,t=%g)' % [r, t] } end - + + # Test if it is possible to create a GSL::Complex from ::Complex + def test_rb_complex_creation + rb_comp = Complex(rand, rand) + + z = GSL::Complex.alloc(rb_comp) + + assert_rel z.real, rb_comp.real, GSL::DBL_EPSILON, + "gsl_complex real part. Re(#{rb_comp}) = #{z.real}" + assert_rel z.imag, rb_comp.imag, GSL::DBL_EPSILON, + "gsl_complex imag part. Im(#{rb_comp}) = #{z.imag}" + end end