Why O2scl?

A brief discussion of the context and future direction for an object-oriented scientific computing library.


C++ has changed


Standards are still young


Vectors, matrices, and other types


Oldies but goodies


Get it working already!


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!

  • Lambda functions make mathematical methods much easier to implement.
  • For example, 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)

  • Template-based classes can operate on functions faster than old C-style function pointers.
  • C-style scientific libraries like GSL accept functions based on function pointers, which means that the code inside the function is not known at compile-time. For C++ classes like o2scl::root_brent_gsl above, because the function type is a template parameter, the C++ compiler can know which function is being solved at compile time, which allows for more optimizations.

On the other hand C++11 support is not universal. (That would be too easy.)

Some high-performance computing machines do not yet have C++11 support for all compilers.

  • For example, some compilers on some NERSC machines do not support all of the C++11 features.
  • O2scl has been successfully used on all of NERSC's largest machines. The next version of will have a configure flag, --disable-cpp11, which ensures compilation with earlier compilers and will use the Boost configuration macros to ensure C++11 is used only when it is supported.

Linear algebra in C++ is still a developing art. (And yes, it is truly an art.)

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. (No single library will solve all your probllems.)

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. 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.