Search code examples
dlinear-algebra

Fixed-Dimension Specialization for Linear-Algebra Packages in D


D can specialize functions on constant arguments (known in compile-time), typically for pow(base, exponent) if exponent is a constant integer. As C++ lacks this feature it instead have to resort to template-specialization-hacks that obscure the API for example the pow function-template in Boost.Units.

But, couldn't constant arguments specialization also be used in linear algebra packages to specialize matrix operations such matrix-vector-multiply for fixed dimension cases such as 2x2, 3x3, 3x3, 4x3 and 4x4 generally used in 2-D/3-D graphics. These overloads are typically implemented using SIMD instructions (intrinsics) and it would be fantastic if these implementations could be picked automatically by such a library for matrices and vectors of suitable fixed size.

I believe this would be a real killer application for D, especially in scientific visualization. This is because the bridge between higher/dynamic-dimension linear algebra and fixed-dimension 2-D/3-D could be made completely transparent to a developer making use of a package implementing these ideas.

There are already several nice 2-, 3-, and 4-D linear-algebra packages for D such as gl3n. I would love to see it be extended to provide functions contained in C++ libraries such as Eigen and Armadillo.


Solution

  • But, couldn't constant arguments specialization also be used in linear algebra packages to specialize matrix operations such matrix-vector-multiply for fixed dimension cases such as 2x2, 3x3, 3x3, 4x3 and 4x4 generally used in 2d/3d graphics.

    Yes, this is entirely possible, and quite easy. There's a few ways you can do it:

    • Use template specialisation.
    • Use template function constraints.
    • Use static if.

    Here's an example using static if for vector addition.

    Vec!N add(int N)(Vec!N a, Vec!N b)
    {
        static if (N == 4)
        {
            // Use vector ops
        }
        else
        {
            // Use generic routine
        }
    }
    

    The static if is evaluated at compile time, so there is no branching cost at run time.