Mind Ramblings My Blog

Common Enumeration in C and C++

Welcome back! Well, I did get most of my pending PRs merged last week, but I won’t go as far to say that I was at my full efficiency. I indeed got entangled in some work and it got me distracted. Good news is Symbol is now officially supported in SymEngine ruby bindings and can be played with from the latest master

In this post, I would like to concentrate more on a hack that we used to use enums in both C and C++, that too within namespaces (within C you say? kinda.), so that they don’t possibly conflict with anything. We automated the whole thing and instantly saw the benefit. We used the same approach for writing the same repetitive method for all classes and came to know that we had somehow missed a method from a class.

The File that has the list

There has to be a file enlisting all the classes,

//File: type_codes.inc
SYMENGINE_ENUM(BASIC),
SYMENGINE_ENUM(INTEGER),
SYMENGINE_ENUM(RATIONAL),
//more 47 lines...

In the C implementation file

//File: cwrapper.h
typedef enum {
    #define SYMENGINE_ENUM(type) SYMENGINE_##type
    #include "symengine/type_codes.inc"
    #undef SYMENGINE_ENUM
    SYMENGINE_TypeID_Count,
} TypeID;

In the C++ implementation file

//File: basic.h
enum TypeID {
    #define SYMENGINE_ENUM(type) type
    #include "symengine/type_codes.inc"
    #undef SYMENGINE_ENUM
    // The 'TypeID_Count' returns the number of elements in 'TypeID'. For this
    // to work, do not assign numbers to the elements above (or if you do, you
    // must assign the correct count below).
    TypeID_Count
};

This is really an elegant solution. This can also be extended to all the other situations where you want to define or do the same thing for all the classes. You just need to enlist them at a certain place and use macros to generate/automate the process of writing the methods. You add a class and those methods get define for the class.

I would highly suggest you to have a look at Issue#520 and PR#540 to have a look at how we extended this approach to automate the long and WET code in Visitor and BaseVisitor classes.

Next Week

I will try my best to get Integer and Rational to get merged during the weekend and during the week I can focus on the Complex class. Also, next week I will focus on unwrapping the data from gmp gem. We use it with SymEngine then why not with its Ruby bindings.

Commits

  • Refactored ruby/ext src files to use basic_new_heap
  • eq() and neq() use the new func sign after PR#508
  • Overrid #eql?, #hash in Basic to compare sets
  • Used basic_new_heap & Data_Wrap_Struct in alloc_func
  • Removed csymbol_alloc and alloc_func
  • Removed cbasic_init, uses default new now
  • Fixed typo in cwrapper
  • Added the C wrapper & its tests for Basic hash
  • Added the Ruby wrappers for hash
  • Changed implementation of basic_hash in cwrapper
  • Enum-Class mapping, selective exclude in type_codes.inc
  • Refactored for new SYMENGINE_ENUM macro signature
  • Used type_codes.inc to simplify code in visitor.h
  • Configured spec_helper to work with test_unit
  • Added test-unit as development dependency
  • Added script to test with valgrind
  • Added script to test with callgrind tool
  • Updated .gitignore


comments powered by Disqus