Mind Ramblings My Blog

The Symbol Class

Hi everyone! The midterm evaluations for GSoC-2015 have arrived. These will last for about a week, in which we will be evaluated on the basis of our performance.

Beginning of this week, I got my PR merged. I had 49 randomly ordered commits that I managed to squeeze into only 13! I can say I have got a very good hold of git rebase -i by now.

This week was spent more towards developing the wrappers for Symbol class, adding methods, writing tests and trying to find memory leaks. The obvious choice to detect memory leaks is Valgrind, but after using RSpec, I am looking for a more Rubyish way to detect memory leaks. I am still going through some guides on how to detect memory leaks, be it Valgrind or something else. Any suggestions will be really appreciated. You can review the work in my PR #480 Support for Symbols in Ruby wrappers.

One of the things I felt like worth writing in a blog post is as follows

Inheritance in Ruby C API

We know how inheritance works in C++, if we have a class, say SubC, that is the subclass of a particular class, say C. When we make an object of the class SubC, the constructor for the class C is called first and then the constructor for SubC along with the initialization that it might need to do. In Ruby, this happens in two steps. One is a method call to .allocate, which is most of the time done internally, and then the method .initialize to initialize the content of the object. So, when I was writing the wrappers for Symbol, Isuru, one of my team-mates, raised this question. Symbol is a subclass of Basic and I have the code in

void Init_symengine() {
    m_symengine = rb_define_module("SymEngine");

    //Basic class
    c_basic = rb_define_class_under(m_symengine, "Basic", rb_cObject);
    rb_define_alloc_func(c_basic, cbasic_alloc);

    //Symbol class
    c_symbol = rb_define_class_under(m_symengine, "Symbol", c_basic);
    rb_define_alloc_func(c_symbol, csymbol_alloc);

Now overloading the allocate method through the C API to set the custom allocate function has been deprecated and it is advised to use the rb_define_alloc_func now. In the method, rb_define_class_under, the third argument is the name of the base class. So the doubt was, will the function cbasic_alloc be called along with csymbol_alloc, since Basic is the base class for Symbol? And also csymbol_alloc did nothing but called the cbasic_alloc function inside it. So, will the function be called twice.

To get the answer, I tried searching on the internet and tried reading the source code, but couldn’t make much sense out of it. Neither anyone had made such classes and wrote about how they behave.

So, I got the function cbasic_alloc to print ‘basic object allocated’ everytime it got called.

VALUE cbasic_alloc(VALUE klass){
    VALUE obj;
    basic_struct *struct_ptr;

    obj = Data_Make_Struct(klass, basic_struct, NULL, cbasic_free, struct_ptr);

    struct_ptr->data = NULL;
    printf("basic object allocated\n");

    return obj;
}

Now normally, expecting the same behaviour as C++ in C API, one would expect to see the message printed twice when a Symbol object was created, but that’s not what I got.

//$ rspec spec --format documentation
SymEngine
  SymEngine::Basic
    .new
      with no arguments
basic object allocated
        returns a Basic object

SymEngine
  SymEngine::Symbol
    .new
      with an integer as an argument
basic object allocated
        returns a Symbol object
    binary operations

Only csymbol_alloc was called when Symbol was instantiated. Maybe the sole responsibility to create an object is given to the function passed. The parameter passed as the base class might only be for identification in Ruby that what is a subclass of whom.

Soon, I will be adding support for Integer and Rational classes after which you will be able to form expressions using integers like (x+y)**2 instead of (x+y)*(x+y). You can follow the work in the PR #487 Support for Integer and Rational classes in Ruby wrappers

Next Week

The plan for next week is to completely support Integer and Rational classes along with automation of testing for memory leaks. I don’t even know, if it would be feasible to integrate testing of memory leaks to Continuous-Integration, but it’s a worth a shot. It will be very convenient to have an alert system that warns you about memory leaks everytime you push the code.

Commits

  • Added source files for symbol
  • Added expand method to Basic
  • Added the to_s method that returns the string rep returns the string representation
  • Added the tests for symbol from basic
  • Moved the symbol related files to symengine/ruby
  • Rearranged the tests betn Symbol and Basic, Corrected the descriptions
  • Added the == operator for Basic class Added test for ==
  • Added method != in Basic
  • Added alloc_func and removed repetitive headers


comments powered by Disqus