Why O2scl?

A brief discussion of the context of this object-oriented scientific computing library.


I needed to provide a computing framework for my research group. (Necessity is the mother of invention.)

I want my students and colleagues to be able to have a head start.

  • There is little point in having a student to rewrite old code over again when there are so many great new problems that need solving.
  • I wanted something easy to install and use.
  • O2scl takes advantage of homebrew and travis-ci.org to make sure installation and testing works.

Scientific computing in C++ has changed significantly in the past few years. (Or maybe a bit more than a few.)

C++0x and C++11 (and their precursors in Boost) have made scientific computing much easier!

  • For example, lambda functions make mathematical methods much easier to implement.
  • Function objects can now be defined and manipulated very succinctly:

    double a=-0.9, b=0.9;
    o2scl::root_brent_gsl<> solver;
    std::function<double(double)> f=[](double x){ return sin(x)-0.1; };
    solver.solve(a,b,f);
    cout << a << endl;
    
    (adapted from O2scl's ex_lambda.cpp example)

  • Sometimes the best solution is a combination of several different languages and libraries.
  • Python has enabled fast development, but we still want fast execution from C++. GSL is great for many problems, but Fourier transforms are better done in FFTW and linear algebra is better implemented in uBlas, Eigen, or Armadillo.

Vector and matrix types have proliferated. (Templates can save us.)

As a result of the complexity of designing a C++ linear algebra library, the current state-of-the-art consists of several C++ linear algebra libraries, each with their own distinct vector and matrix types.

  • Among these options are uBlas, Eigen, Armadillo, and more. However, none of them seem to agree on the basics of how these objects should be written. For example, consider the basic reallocation method, resize(). In the C++11 standard, this is written

    void std::vector::resize(size_type n)

    and it is assumed that the action of resize() is destructive. On the other hand, in uBlas, resizes are non-destructive by default

    void ublas::vector::resize(size_type n, bool preserve=true)

    Armadillo vectors follow the same behavior of std::vector for destructive resizes, but introduce a new notation for non-destructive ones

    void arma::row::set_size(size_t n)
    Eigen operates similarly, but uses the name conservativeResize() for non-destructive resizes. O2scl, for the time being, presumes that all resizes are destructive, and uses a notation similar to the C++11 standard for its resize methods.

    (Eventually, a set of linear algebra type traits is necessary to describe how linear algebra types behave and how they interact with each other. )

  • Obtaining rows and columns of matrices (without a copy) is also not trivial. In uBlas, the row of a matrix is obtained by using the constructor of a matrix_row object. In Armadillo and Eigen, this is performed by using the .row() method, resulting in a vector object of an unusual type. O2scl subsumes some of this complexity into a function o2scl::matrix_row, which can be used with any of these linear algebra libraries

    // With uBlas
    typedef boost::numeric::ublas::matrix<double> matrix;
    typedef boost::numeric::ublas::matrix_row<ubmatrix> matrix_row;
    matrix_row r1=o2scl::matrix_row<matrix,matrix_row>(m1,2);
    // With Eigen
    Eigen::MatrixXd::RowXpr r2=
    o2scl::matrix_row<Eigen::MatrixXd,Eigen::MatrixXd::RowXpr>(m2,2);
    // With Armadillo
    arma::subview_row<double> m1=
    o2scl::matrix_row<arma::mat,arma::subview_row<double> >(m3,2);
    

  • Heterogeneous architectures also naturally lead to more data types to help contain and manipulate data on them. The issues described above will likely become more commonplace.

  • At the same time, C++ offers quite a bit of syntactic simplicitly, with relatively little cost in speed. Even though linear algebra libraries do not agree on the details of the interface, they can speed up development time considerably.

There is no “one-stop shopping” solution for scientific computing. (We try to combine several tools in a useful way.)

Boost, while well-developed, doesn't provide direct solutions for some basic problems, such as numerical differentiation and nonlinear solving.

  • GSL does, of course, but is more difficult to use with C++ member functions and generic vector types. Two-dimensional interpolation has only recently found its way into the GSL repository yet has been in O2scl for many years. (In fact, some GSL improvements were guided by O2scl development.)

O2scl is a work-in-progress. (Help me Obi-Wan!)

O2scl attempts to be a path towards a general-purpose C++ scientific computing library which enables easier and faster development.

  • O2scl is still in beta, so this is a perfect time to let me know if it is useful to you (or not), and feel free to make comments or suggestions.


    Built with Bootstrap.