Skip to content

GSoC 2015 Abinash Meher: Ruby bindings for CSymPy

Abinash Meher edited this page Apr 28, 2015 · 14 revisions

Ruby bindings to the CSymPy C++ symbolic library

Motivation

The motivation was to have a computer algebra system for Ruby. At the beginning, the idea was to use ruby wrapper for sage which uses Pynac for its symbolic manipulation (Pynac is a Python interfact to GiNaC and CLN), because it is much faster.
However, from the benchmarks, CSymPy is much faster than Pynac. The reason Pynac is slower is probably because it uses Sage's GMP functionality. In case of CSymPy there is no Python being called from the C++ code. The code is entirely in C++. It was for this reason that there's no need to worry about any potential Python overhead. It also allows us to use it from other languages, with the help of wrappers.
Another option was to wrap GiNaC directly, but CSymPy also seems to be a bit faster than GiNaC itself by now. The code has been designed in such a way so that one can play with various data structures and really make sure the code is fast.
There is one small limitation however. Compared to GiNaC, CSymPy is missing specialized polynomial manipulation and series expansion and pattern matching, all of which are being worked on and will get the functionality soon. Most part of it might get completed during this summer as part of GSoC projects. Execution

  1. Tool to generate the wrappers
    There were many choices like Ruby inline, Rice, FFI, SWIG and manually using Ruby C API . From the first 3 FFI seems to be the fastest as benchmarked in this link. However, with the FFI method, we get a segfault at runtime while running Ruby tests (which we will be adding whatever tool we use). Here manual method is advantageous since it is compiled, so we immediately get a compile error on Travis if we change an interface in CSymPy, so we know we have to fix it, while merging the patch. It will be a huge comfort. Also, the manual method is preferred while dealing with a lot of pointers in the C++ code. Because either way we would end up doing as much work. Also the code is clearer in the manual method. With SWIG, C++ references are supported, but SWIG transforms them back into pointers, as mentioned here. It's a feature that we might be needing some time later. So, going with the manual method seems the wisest.

  2. File structure
    Currently all the python wrappers are in a folder csympy under the root folder. The idea is to keep all the wrapper code at a single place, i.e. inside the src in separate folders like src/c, src/python and src/ruby. The same logic can be applied to other languages later like src/julia, etc.
    Each folder can then be configured to a ready to install package like the python wrappers as a pip-package and the ruby wrappers as a gem.

  3. Exposing the C++ functions to C with extern "C"
    Ruby provides interfacing to only C functions. For that we need to expose the C++ code through extern. The functions can now be called from C. Let's take an example C++ class, using one header file (Test.hpp) for demonstration

//File: Test.hpp
class Test {
    public:
        int testfunc();
        Test();

    private:
        int testint;
};

and one implementation file (Test.cpp)

//File: Test.cpp
#include <iostream>
#include "Test.hpp"

using namespace std;

Test::Test() {
    this->testint = rand()%1000 ;
}

int Test::testfunc() {
    return this->testint;
}

This is how csympy is structured, C++ code that does the actual job.

We will have some glue code. This code is something in-between C and C++. We will have one header file (TestWrapper.h, just .h as it doesn't contain any C++ code)

//File: TestWrapper.h
#include <ruby.h>
typedef void CTest;

#ifdef __cplusplus
extern "C" {
#endif

static VALUE test_alloc(VALUE self);
static VALUE test_initialize(VALUE self);
static VALUE test_testfunc(VALUE self);
void test_delete(CTest *t);

#ifdef __cplusplus
}
#endif

and the function implementations (TestWrapper.cpp, .cpp as it contains C++ code):

//File: TestWrapper.cpp
#include "TestWrapper.h"
#include "Test.hpp"

extern "C" {

    void test_delete(CTest *test) {
        Test *t = static_cast<Test *>(test);
        delete t;
    }

    static VALUE test_alloc(VALUE self) {
        Test *data = new Test();
        data = static_cast<CTest *>(data);
        return Data_Wrap_Struct(self, NULL, test_delete, data);
    }

    static VALUE test_testfunc(VALUE self) {
        Test * data;
        Data_Get_Struct(self,Test,data);
        return INT2NUM(data->testfunc());
    }

    static VALUE test_initialize(VALUE self) {
        //nothing to do in this case
        return self;
    }
}

These are the wrappers that expose the C++ functions to C.

  1. Writing the extensions with Ruby C API
    Since the Ruby interpreter is implemented in C, its API can be used. This is called the Ruby C API. It can be accessed with the inclusion of a single file #include <ruby.h>.

"Everything you can do in Ruby, you can also do using [the] C API"

ruby.h contains all the datatypes, C functions and MACRO definitions to be able to interface C/C++ with Ruby.
Every Ruby type/class is a VALUE C type. VALUE is a just a uintptr_t C type, or void* to simplify things. There is also another type representing Ruby symbols (like :my_symbol), this is the C type ID. Ruby C API also defines a bunch of handful C constants defining standard Ruby objects.
There are macros defined to convert the C types to the ruby types. Rest all are C functions that define modules, classes, and their instance and class methods. There are also functions to raise exceptions.
With some more effort, even threading can be implemented.
See The Definitive Guide to Ruby's C API for more details.
For example, doing this for the Test class we get.

//File: ruby_TestWrapper.c
#include <ruby.h>
#include "TestWrapper.h"

static VALUE m_testmodule;
static VALUE c_test;

void Init_testmodule() {  //this is called when we call require 'testmodule' in ruby
    m_testmodule = rb_define_module("TestModule");
    c_test = rb_define_class_under(m_testmodule,"Test",rb_cObject);

    rb_define_alloc_func(c_test, test_new);
    rb_define_method(c_test, "initialize", test_initialize, 0);
    rb_define_method(c_test, "testfunc", test_testfunc, 0);
}

Since everything is not covered, you can refer to the documentation for this from README.EXT. Also the Chris Lalancette's blog.

  1. mkmf and extconf.rb
    The extconf.rb configures a Makefile that will build our extension based. The extconf.rb must check for the necessary functions, macros and shared libraries your extension depends upon. The extconf.rb must exit with an error if any of these are missing. It requires the mkmf or the MakeMakefile module for that matter. The extconf.rb would look like
require 'mkmf'

#Gives the ability to easily use alternate compilers to build the extension
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']

extension_name = 'csympy'

#Check to see if the csympy library required to build this extension exists.
#Typically, we would want to use libcsympy installed, including the header files
unless pkg_config('libcsympy')
      raise "libcsympy not found"
end

have_func('useful_function', 'libcsympy/lib.h')#if found, will define a HAVE_USEFUL_FUNCTION in extconf.h
have_type('useful_type', 'libcsympy/lib.h')#if found, will define a HAVE_TYPE_USEFUL_TYPE in extconf.h

#creates the header file extconf.h, based on the results from all of the previous have_*() functions.
#The extconf.h file will be included by all of the C files in the project 
#to gain access to the HAVE_* macros that extconf defines.
create_header

create_makefile(extension_name)
  1. Data structures in CSymPy
    CSymPy uses some STL data types like std::vector and std::map. These map cleanly to the Array and Hash in Ruby.

We will only need to interface the data between both of them only in the case of when the underlying C++ functions return these data types, not when they are used as member variables. Because we are passing the objects as simple pointers of type void * and again casting them (either static_cast or reinterpret_cast) back to the object inside the C function call implementation. Assuming all the member variables of the class are private and interacts only with methods, there is no need to worry about having a similar internal structure as the C++ one in Ruby. We just have to worry about interfacing the member functions. Even if the corresponding implementation of the data types in Ruby turns out to be slow, we won't be affected by it, except when a new similar large data type is to be made to be returned.

So, we are not losing out on speed that CSymPy offers.

Please see Part-9 and Part-10 of this blog for more information about interfacing Arrays and Hashs.

  1. Exception Handling
    All the C++ code that is to be interfaced will have to be wrapped with a C function first, to be used with the Ruby C API. However in C, there doesn't seem to be a way to handle the exceptions that the underlying C++ code might throw. Therefore all the exceptions will have to be handled in the underlying C++ code itself. Since the ruby C API defined exceptions can also be called from C++ the idea is to catch the exceptions from the underlying C++ code and rethrow it with rb_raise after copying the required information from the exception passed. This is possible because they are compiled with a cpp compiler. For example, let's say that the member function Test::test_func() throws an exception. This is how we will be changing the TestWrapper.cc file
//the previous function definition of test_testfunc will be replaced by
static VALUE test_testfunc(VALUE self) {
    try{
        Test * data;
        Data_Get_Struct(self,Test,data);
        return INT2NUM(data->testfunc());
    }catch(ExceptionClass1 e1){
        VALUE exception;
        //Copy the required information from e1
        //to exception;
        exception=rb_exc_new2(rb_eException, "Error message");
        rb_iv_set(exception, "@additional_info",
                 rb_str_new2("information from e1"));
        rb_exc_raise(exception);
    }
}

This is not final, please refer here for an ongoing discussion.

  1. Garbage Collection
    Ruby 2.1 introduced a generational garbage collector (called RGenGC). RGenGC (mostly) keeps compatibility. Generally, the use of the technique called write barriers is required in extension libraries for generational GC. RGenGC works fine without write barriers in extension libraries. However, caring about write barrier can improve the performance of the GC.
    But we won't need to if we are using built-in types from Ruby C API. Most built-in types support write barrier. If we are using the T_DATA datatype from ruby, which doesn't have write barriers, we might have to write one. But that is strongly discouraged since writing write barriers are easy to introduce critical bugs and there is too much risk associated with it. We won't use T_DATA unless there's no other way.
    For this to work properly it's advised not to touch the pointers directly. Rather use the C-API's methods to acquire pointers to the internal data structures.

While using the C API, there won't be the need to 'mark' each data we define, if they are defined following the proper allocation framework(Given in the Ruby Hacking Guide) using Data_Wrap_Struct() and Data_Get_Struct(), or using the given ruby C functions for that purpose, like rb_class_new_instance(). The functions mark them internally, and is taken care of automatically by the GC.

Also, there will be issues because of the optimizing C compilers. Since they are not designed with conservative GC in mind, they might optimize away the original VALUE even when the code depends on it. Also sometimes a variable might get GC'ed when we don't want it to. To prevent such premature GC, we will use RB_GC_GUARD() macro which comes with Ruby C API and needs to be called after the last usage of the variable. There might be times when this doesn't work, like when the VALUEs are in the heap storage and we do not want them on the stack for the time they are not to be GC'ed, we can hack the functions in API to mark them for the time and develop our own functions to do this, like NM_GC_(UN)REGISTER functions in NMatrix.

Also, there might be times when we are sure that a particular object is not needed anymore and can be GC'ed rb_gc_force_recycle() can be invoked. It let's users mention explicitly to collect a particular object.

I don't think that the RCP(either the Teuchos or the csympy implementation) used in csympy will interfere with the wrappers, since they are used with the underlying C++ functions to be wrapped. We still cannot eliminate the possibility.

  1. Ruby Interface
    This is a crucial factor when it comes to writing a library for ruby. This project may not involve writing complete library but also it doesn't involve writing only the extensions. This also incorporates designing a proper interface that suits the style of coding in Ruby. Again, this can't be achieved at once, but will require feedback from people who use the wrappers. I sure would like to have the wrappers have a rubyish interface. However, This is a long term process. My first goal would be to clone the C++ wrappers as faithfully as I can, and then second would be to improve upon the base design, incorporating things like blocks, procs, mixins, named methods, etc. that are characteristic of ruby. The latter might require writing additional classes. For the time being, I will follow the ruby convention of naming the methods and variables (e.g. ending with ?, etc.).

  2. Making this a gem
    Making this available as a gem will make it very easy to install. The ease of installation can be very important factor when it comes to user engagement. User will have the choice if (s)he wants to install the wrappers along with csympy or only the wrappers(in case he has csympy already). A check can be included to automate this. We will also need a functionality to just compile the extensions separately than the library.

Tools I am going to use

I am using a system dual-booted with Ubuntu 14.04.2 LTS and Windows 8.1. Following are the configurations on my machine

abinashmeher999@JARVIS:~$ ruby --version
ruby 2.0.0p598 (2014-05-08 revision 45883) [x86_64-linux]
abinashmeher999@JARVIS:~$ gem --version
1.8.23
abinashmeher999@JARVIS:~$ rake --version
rake, version 10.0.4
abinashmeher999@JARVIS:~$ rspec --version
3.2.2
abinashmeher999@JARVIS:~$ bundle --version
Bundler version 1.3.5
abinashmeher999@JARVIS:~$ rdoc --version
rdoc 3.9.5
abinashmeher999@JARVIS:~$ rvm --version
rvm 1.26.10 (latest) by Wayne E. Seguin <[email protected]>, Michal Papis <[email protected]> [https://rvm.io/]
abinashmeher999@JARVIS:~$ valgrind --version
valgrind-3.10.0.SVN

I am using RVM to manage the ruby versions in my system. Besides that, I will be using vim as my primary text editor. Apart from that I will be using the following

  • Rake-compiler
    rake-compiler is a set of rake tasks for automating extension building. Rake eases the process of making extensions by its 'rake/extensiontask'. If a proper project structure is followed, generating extensions requires only a few lines of code.
  • RSpec
    RSpec tests it the way a developer would like it to, to make sure all works as (s)he intended them. More like the unit tests. Whereas, Cucumber tests it the way a client/consumer would expect from the software. Like the integration tests. Most of the places, people suggest that both go hand in hand. But since the underlying C++ code is tested elsewhere, integration testing won't be needed.
  • Bundler
    Bundler provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed. It ensures that the gems you need are present in development, staging, and production.
  • RDoc
    For documentation of code and tests. I would also like to look into to generate ri(ruby interactive) documentation if time permits.
  • Valgrind
    Valgrind is a tool suite that automatically detects many memory and thread related problems with an application. It's composed of few tools, each designed to track different kind of problems like detect bad memory usage, detect memory leaks, profile heap usage, etc. This will prove to be a very useful to check for memory leaks from the extension code. I wil be using it to check for memory leaks in the C code.

Timeline (tentative)

New Proposed Timeline

The new timeline is inspired by Test-Driven Development that will break down the entire task of writing wrappers into modules that can be subsequently tested and deployed as they develop, into a minimal gem. This way we can get feedback early. This will involve writing the tests before writing the code. These tests will set short term goals for the wrappers. After the tests pass, they can be directly merged with the codebase and hence to the gem.

The whole task can be divided into 5 phases, each with their short-term goal/test to achieve. The phases consist of one or more units that can be introduced as a feature to the gem which we will build upon. And the tests that the code should pass, will be divided as one test file for each unit.

Before the phases begin, some preparations will also be done for setting up the basic framework of the wrappers and the units will be subsequently added after that.

Also each of the units will involve first writing the tests, then writing the function declaration for the pure C wrappers and their definition, then writing the C ruby wrappers declaration and definition, and finally writing them in the Init_csympy(). In short, I will be going through the cycle of my old timeline for each of these units.

I will use the test files for the python wrappers as a reference. They have given a vague idea on how to proceed.
Documenting them are an obvious task.

  1. Phase 1 : Symbol, its dependent classes and Parsing
    Estimated time: 2 Weeks
  • After this, the gem will support Symbol class and classes like Integer, Rational and Complex .

  • The gem will also support parsing of strings as expressions of symbols.

  • The corresponding test files will be the RSpec equivalent of test_symbol.py, test_integer.py and test_sympify.py.

    1. Phase 2 : arit and subs
      Estimated time: 2 Weeks
  • The gem will support all the arithmetic operations like addition, multiplication and exponentiation of symbols.

  • It will also support substitution of one symbol by other symbols. Might be useful for evaluation of expressions later.

  • The corresponding test files will be the RSpec equivalent of test_arit.py and test_subs.py.

    1. Phase 3 : eval and functions
      Estimated time: 2 Weeks
  • After this, the gem will support evaluation of expressions by substituting symbols with numbers.

  • It will also support function_symbols, and all the arithmetic operations on functions. It will also support derivative of them.

  • I will also add the trigonometric functions after the above. However, we may need a different test files for them.

  • The corresponding test files will be the RSpec equivalent of test_eval.py and test_functions.py.

    Till Mid-Term I would have covered upto eval/evaluation of expressions. That's the minimum target. If possible I would like to finish this early to concentrate on later parts.

    1. Phase 4 : matrices
      Estimated time: 2 Weeks
  • After this, it will support symbolic operations on the elements of matrices.

  • As well as arithmetic operations on matrices that have symbols.

  • The corresponding test files will be the RSpec equivalent of test_matrices.py.

    1. Phase 5 : ntheory
      Estimated time: 2 Weeks
  • This will add support for all the functions corresponding to number theory in csympy, like mod, quotient, quotient_mod, mod_inverse, etc.

  • These will also support operations like lcm, gcd, finding primes, etc.

  • The corresponding test files will be the RSpec equivalent of test_ntheory.py.

    I have kept 2 weeks at the beginning for Community bonding and learning the things that I am yet to learn, and 2 weeks at the end as a buffer time, to compensate for my 8 day absence and catching up.

Community Bonding period (27th April - 24th May) and Week 1

  • I don't know everybody yet, neither did I get enough time to know at least a few developers in the community before the application. This will be a great time to get to know everybody and the fellow students. My summer vacation will start from 29th of April.
  • The remaining time will be devoted to integrating making of ruby extensions from cmake, by invoking rake from cmake. So that the building of extensions can be checked by travis. Travis is already integrated with csympy.

Week 2

  • I can get up to speed by reading the documentation and getting to know the practices followed in the community. While I don't claim to know how to use the tools that I mentioned, this will be the time, I learn them.
  • I will also use this time to read the documentation for the tools I will be using, so that I know how to use them properly and am aware of the best way to achieve the result and make informed decisions.
  • I will also set a dummy gem with no functionality so that the functionalities are added as they are interfaced. The gem will be published after 2 weeks from now.

Week 3

  • This week I will write tests and interface Symbol class and other dependent classes like Integer, Complex and Rational.

Week 4

  • This week I will be working to achieve Parsing to symbols from text. Tests will precede this.
  • Also start working on the arithmetic operations.

Week 5

  • This week will be devoted towards supporting arithmetic operations with symbols and testing them.
  • Start writing the tests for subs.

Week 6

  • This week will be devoted to supporting substitution with symbols in expressions.
  • If time is left I will start working on function_symbols and evaluation of expressions.

Week 7

  • Writing target tests and interfacing eval that will make evaluation of expressions possible. If this finishes early I can start on function_symbols, because other trigonometric functions might will take more time.
  • By the end of this week, for the Mid-term the gem will have the functionality for all the above phases.

Week 8

  • I will write target tests for the trigonometric functions, substitution of function_symbols and many more. Then implement the all the C and Ruby wrapper for them just like the previous ones.

Week 9 and Week 10

  • This week will be dedicated to achieve arithmetic operations with matrices that have symbols as their elements.
  • The rest of the week will be devoted to implement the features tested in test_ntheory.py. They are a bunch of features and we might need to use a bit of our buffer week too.

Week 11

  • These two weeks will mainly focus on interfacing the number theory and like functions. However, I still aim to cover some part of this earlier. Because one week might not be enough as I have written in the phase description.
  • This will most probably be covered within this week. If not, I will extend it to the Buffer period.

Buffer Period and Week 12 and 13

This week is the buffer and a precaution for everything that might delay the completion. This will mostly involve

  • cleaning up the code and refactoring, fixing bugs and documentation
  • addition of more tests, examples and everything that's pending
  • Make sure the installation works on all systems

Note:

During the whole GSoC, I will be blogging weekly about my progress and experience at this blog. The timeline might seem sparse as at this moment I am not able to judge how much time each work is going to take. If something is finished before time, I will proceed to the next part. Also there is the buffer period in case a bug pushes things down the line.

Post GSoC

  • I will try to write some benchmarks for the ruby wrappers if the time permits and any of the buffer period in still left.
  • I will try to include the functionality that csympy currently lacks but will most likely get as a result of the GSoC. I will be able to contribute during my semester, but not as effectively as during the summer. This could be completed by end of winter(December) holidays.

Previous Timeline (for reference)

The project will consist of four phases.

  1. Phase 1 : Writing the C wrappers
    Estimated time: 2 Weeks
    The first step would be to write pure C wrappers for the C++ code, so that we create some reusable code since we are interfacing through C, that can be used for some other languages. This will involve
  • writing function declarations in header files,

  • their definitions in source files,

  • creating new structs maybe,

  • error handling (returning error codes) and

  • documentation. 2. Phase 2 : Writing the Ruby wrappers
    Estimated time: 3 Weeks
    This will be the code that will be in C and will use Ruby C API to interface the created pure C functions to Ruby. This will involve

  • writing function declarations in header files,

  • writing their definitions in source files,

  • exception handling (raising exceptions in Ruby),

  • managing garbage collection,

  • defining module, its classes and methods in Init_csympy and

  • configuring extconf.rb

  • documentation 3. Phase 3 : Writing the Tests (RSpec)
    Estimated time: 2.5 Weeks
    This the phase where we test that our code is working and not leaking memory. If anything is wrong, we make sure that the extension is working. This involves

  • Setting up the rake tasks,

  • Invoking rake commands from cmake,

  • Writing tests using RSpec

  • Checking for memory leaks using Valgrind

  • Fixing bugs 4. Phase 4 : Packaging and Wrap up
    Estimated time: 1.5 Weeks
    In this phase, we make the set of extensions readily available to be installed and used. The rest of the time is used to do cleanup of code, and fixing bugs. This involves

  • Clean up and refactoring, if needed

  • Fixing bugs

  • Packaging it as a gem

  • Making sure it works and installs for all platforms

  • Publishing the gem to rubygems.org

    I have kept 2 weeks at the beginning for Community bonding and learning the things that I am yet to learn, and 2 weeks at the end as a buffer time, to compensate for my 8 day absence and catching up.

Community Bonding period (27th April - 24th May) and Week 1

  • I don't know everybody yet, neither did I get enough time to know at least a few developers in the community before the application. This will be a great time to get to know everybody and the fellow students. My summer vacation will start from 29th of April.

Week 2

  • I can get up to speed by reading the documentation and getting to know the practices followed in the community. While I don't claim to know how to use the tools that I mentioned, this will be the time, I learn them.
  • I will also use this time to read the documentation for the tools I will be using, so that I know how to use them properly and am aware of the best way to achieve the result and make informed decisions.

Week 3

  • This week will be dedicated to make the header files in src/c(the place for pure C wrappers), that contain the C function prototypes with extern "C", with C++ code in them. The interface between C and C++.
  • Also I will prefer to document the functions.

Week 4

  • This week has, writing the function definition for the declarations in the header files for the pure C wrappers. Error handling will be done the standard way upon catching any exceptions. This part won't use Ruby C API.
  • Also documenting it on the go.

Week 5

  • This week's task will be to write the header files, that contain the C function prototypes for the Ruby wrappers. These will go to the folder src/ruby. These will not be the same as the earlier ones since these will use the Ruby C API.
  • Defining some additional MACROs for GC as discussed above. Also documenting the code.

Week 6

  • This week involves writing the implementations/function declarations for the ruby-wrapper C header files in src/ruby(the ones that use Ruby C API). This will also include having proper exception handling along with the guarantee they provide, and looking for places where GC might prematurely collect.
  • Some custom data types might need making custom classes and that would require writing write barriers.
  • This will also involve documenting the implementation.

Week 7

  • I will completely devote this week to writing the actual Ruby wrappers in the Init_csympy function, the function that will initialise the module. This function will contain calls to the Ruby C API functions to define the module, the classes and their methods.

Week 8

  • I will devote this week to configure the extconf.rb using FLANN's extconf.rb as a model, and extensively cover all the rake tasks that would be needed for the building of extensions and the tests.
  • The remaining time will be devoted to integrating making of ruby extensions from cmake, by invoking rake from cmake. So that the building of extensions can be checked by travis.

Testing and Week 9

  • This week will involve writing the unit tests and carrying them out using RSpec.
  • Special tests that involve writing the possible memory leaking piece of code and running it in a loop, and checking the memory usage during that period. More details here. Valgrind might be useful for this.
  • Also automating the above tests.

Testing and Week 10

  • After writing the tests, bugs and errors are sure to pop up. This week will be devoted to fix them. This includes finding and fixing memory leaks and making sure garbage collection works properly. I might have to delve deeper into garbage collection in order to fix the problem. This might involve using low level functions in API as a hack.
  • The rest of the time I will devote to make improvements in the interface, the way they will be called from Ruby code, trying to accommodate the ruby coding style with the function calls.

Packaging and Week 11

  • This week I will devote to making this project a gem, that will check if all the dependencies are met on the system to be installed. If not, it might provide the libraries of csympy that can be used to build the extensions or ask the user to resolve them.
  • Following the procedure I will publish this gem to the rubygems.org, so that it can be easily installed from command line.
  • I will also test the installation on all platforms using Travis.

Buffer Period and Week 12 and 13

This week is the buffer and a precaution for everything that might delay the completion. This will mostly involve

  • cleaning up the code and refactoring, fixing bugs and documentation
  • addition of more tests, examples and everything that's pending
  • Make sure the installation works on all systems

Note:

During the whole GSoC, I will be blogging weekly about my progress and experience at this blog. The timeline might seem sparse as at this moment I am not able to judge how much time each work is going to take. If something is finished before time, I will proceed to the next part. Also there is the buffer period in case a bug pushes things down the line.

Post GSoC

  • I will try to write some benchmarks for the ruby wrappers if the time permits and any of the buffer period in still left.
  • I will try to include the functionality that csympy currently lacks but will most likely get as a result of the GSoC. I will be able to contribute during my semester, but not as effectively as during the summer. This could be completed by end of winter(December) holidays.

Relevant Issues/ Discussions and References

[1] https://groups.google.com/forum/#!topic/sciruby-dev/vIgrXnI5eq8
[2] https://groups.google.com/forum/#!topic/sciruby-dev/iVRxZX4m7cU/discussion
[3] https://groups.google.com/forum/#!searchin/sciruby-dev/csympy/sciruby-dev/Cb59l2sFlhU/nqptwJFjRGgJ
[4] Calling C/C++ from Ruby
[5] SWIG and C++ - References and Pointers
[6] File structure for Ruby extension #413
[7] Calling C++ class method from C
[8] How to mix C and C++
[9] Wrapping C++ class API for C consumption
[10] README.EXT Documentation
[11] The Definitive Guide to Ruby's C API
[12] Chris Lalancette's blog - Writing Ruby extensions in C
[13] Gems with Extensions
[14] rake-compiler - Github
[15] Brian Guthre's blog - When to use RSpec, when to use Cucumber
[16] Bundler
[17] Garbage Collection | Ruby Hacking Guide
[18] GC Management Changes (also list/yale inject rank, slicing bugfixes) #160
[19] Figure out a way for exception handling with C wrappers #418

Clone this wiki locally