259

It seems that many projects slowly come upon a need to do matrix math, and fall into the trap of first building some vector classes and slowly adding in functionality until they get caught building a half-assed custom linear algebra library, and depending on it.

I'd like to avoid that while not building in a dependence on some tangentially related library (e.g. OpenCV, OpenSceneGraph).

What are the commonly used matrix math/linear algebra libraries out there, and why would decide to use one over another? Are there any that would be advised against using for some reason? I am specifically using this in a geometric/time context*(2,3,4 Dim)* but may be using higher dimensional data in the future.

I'm looking for differences with respect to any of: API, speed, memory use, breadth/completeness, narrowness/specificness, extensibility, and/or maturity/stability.

Update

I ended up using Eigen3 which I am extremely happy with.

halfer
  • 18,701
  • 13
  • 79
  • 158
Catskul
  • 15,635
  • 13
  • 75
  • 111
  • 2
    Since you mentioned OSG and OpenCV, I'm guessing you just need 3D graphics type vector/matrices, ie: 3x3 and 4x4 matrices. I based my answer off that, but you may want to specify how exactly you're using this - do you need matrix solving? Higher dimensional matrix math? etc. – Reed Copsey Sep 04 '09 at 16:59
  • Right now I'm only doing 2D geometry based stuff, but hypothetically you sometimes need 3x3 operations on 2D data, and it's unclear if 3D data an thus 4x4 operations might be necessary. We'd like to use a common library across the company. I don't have a good sense for what the tradeoff's would be. More general would be better, but at what cost is the question. – Catskul Sep 04 '09 at 17:11
  • 1
    If you're just doing geometric transformations, I'd really recommend looking at GGT, as I mentioned in my answer. It's very complete for that, but really does nothing BUT that, so it's a very clean, easy option. BLAS and LAPACK are more for doign complex matrix solutions (ie: 50x50 matrices, sparse matrices, etc) for scientific and mathematics, not geometric transformations. – Reed Copsey Sep 04 '09 at 17:39
  • C++ Vector Class Library does parallel processing using SIMD instructions. https://github.com/vectorclass/version2 – A Fog Feb 05 '21 at 10:03

11 Answers11

122

There are quite a few projects that have settled on the Generic Graphics Toolkit for this. The GMTL in there is nice - it's quite small, very functional, and been used widely enough to be very reliable. OpenSG, VRJuggler, and other projects have all switched to using this instead of their own hand-rolled vertor/matrix math.

I've found it quite nice - it does everything via templates, so it's very flexible, and very fast.


Edit:

After the comments discussion, and edits, I thought I'd throw out some more information about the benefits and downsides to specific implementations, and why you might choose one over the other, given your situation.

GMTL -

Benefits: Simple API, specifically designed for graphics engines. Includes many primitive types geared towards rendering (such as planes, AABB, quatenrions with multiple interpolation, etc) that aren't in any other packages. Very low memory overhead, quite fast, easy to use.

Downsides: API is very focused specifically on rendering and graphics. Doesn't include general purpose (NxM) matrices, matrix decomposition and solving, etc, since these are outside the realm of traditional graphics/geometry applications.

Eigen -

Benefits: Clean API, fairly easy to use. Includes a Geometry module with quaternions and geometric transforms. Low memory overhead. Full, highly performant solving of large NxN matrices and other general purpose mathematical routines.

Downsides: May be a bit larger scope than you are wanting (?). Fewer geometric/rendering specific routines when compared to GMTL (ie: Euler angle definitions, etc).

IMSL -

Benefits: Very complete numeric library. Very, very fast (supposedly the fastest solver). By far the largest, most complete mathematical API. Commercially supported, mature, and stable.

Downsides: Cost - not inexpensive. Very few geometric/rendering specific methods, so you'll need to roll your own on top of their linear algebra classes.

NT2 -

Benefits: Provides syntax that is more familiar if you're used to MATLAB. Provides full decomposition and solving for large matrices, etc.

Downsides: Mathematical, not rendering focused. Probably not as performant as Eigen.

LAPACK -

Benefits: Very stable, proven algorithms. Been around for a long time. Complete matrix solving, etc. Many options for obscure mathematics.

Downsides: Not as highly performant in some cases. Ported from Fortran, with odd API for usage.

Personally, for me, it comes down to a single question - how are you planning to use this. If you're focus is just on rendering and graphics, I like Generic Graphics Toolkit, since it performs well, and supports many useful rendering operations out of the box without having to implement your own. If you need general purpose matrix solving (ie: SVD or LU decomposition of large matrices), I'd go with Eigen, since it handles that, provides some geometric operations, and is very performant with large matrix solutions. You may need to write more of your own graphics/geometric operations (on top of their matrices/vectors), but that's not horrible.

Reed Copsey
  • 522,342
  • 70
  • 1,092
  • 1,340
  • Did you evaluate other libraries before deciding on GMTL? Superficial comparison lead me to believe that Eigen was better supported, but thats on the basis of reviewing the respective websites. Are you aware of any specific advantages of one over the other? – Catskul Sep 09 '09 at 14:22
  • Eigen works well, too. It was not as mature at the time I did my investigation, but I believe it would be a good option at this point. GMTL has been used fairly widely, and was very mature and solid when I decided to use it. – Reed Copsey Sep 09 '09 at 14:23
  • I guess to pare down my question to the very crux: Did you make your choice subjectively like "This looks better" or where there specific features (api, speed, memory use, breadth, narrowness, extensibility) that made the difference. I suppose maturity falls under this criteria, but if maturity were the only metric, I imagine you would have selected a BLAS or LAPACK based option. – Catskul Sep 09 '09 at 17:54
  • I chose this after trying multiple options, and based it off: performance, usability, and low runtime/compile time overhead. Eigen looks much better now than it did at that point, so I can't judge between them. However, I've been very happy with GMTL for our uses. – Reed Copsey Sep 09 '09 at 18:05
  • That's part of why I like GMTL, and used it. It just felt very natural to use, and was very, very easy to work with. It also supported everything I needed, in this case, since I was just worried about directly handling geometric transformation and quaternion rotations. – Reed Copsey Sep 17 '09 at 15:45
  • See also this discussion: http://scicomp.stackexchange.com/questions/351/recommendations-for-a-usable-fast-c-matrix-library – Damien Aug 15 '13 at 02:10
  • GNU Scientific Library (for C) has BLAS support as well. https://www.gnu.org/software/gsl/ – Reza Sep 09 '15 at 17:16
39

So I'm a pretty critical person, and figure if I'm going to invest in a library, I'd better know what I'm getting myself into. I figure it's better to go heavy on the criticism and light on the flattery when scrutinizing; what's wrong with it has many more implications for the future than what's right. So I'm going to go overboard here a little bit to provide the kind of answer that would have helped me and I hope will help others who may journey down this path. Keep in mind that this is based on what little reviewing/testing I've done with these libs. Oh and I stole some of the positive description from Reed.

I'll mention up top that I went with GMTL despite it's idiosyncrasies because the Eigen2 unsafeness was too big of a downside. But I've recently learned that the next release of Eigen2 will contain defines that will shut off the alignment code, and make it safe. So I may switch over.

Update: I've switched to Eigen3. Despite it's idiosyncrasies, its scope and elegance are too hard to ignore, and the optimizations which make it unsafe can be turned off with a define.

Eigen2/Eigen3

Benefits: LGPL MPL2, Clean, well designed API, fairly easy to use. Seems to be well maintained with a vibrant community. Low memory overhead. High performance. Made for general linear algebra, but good geometric functionality available as well. All header lib, no linking required.

Idiocyncracies/downsides: (Some/all of these can be avoided by some defines that are available in the current development branch Eigen3)

  • Unsafe performance optimizations result in needing careful following of rules. Failure to follow rules causes crashes.
    • you simply cannot safely pass-by-value
    • use of Eigen types as members requires special allocator customization (or you crash)
    • use with stl container types and possibly other templates required special allocation customization (or you will crash)
    • certain compilers need special care to prevent crashes on function calls (GCC windows)

GMTL

Benefits: LGPL, Fairly Simple API, specifically designed for graphics engines. Includes many primitive types geared towards rendering (such as planes, AABB, quatenrions with multiple interpolation, etc) that aren't in any other packages. Very low memory overhead, quite fast, easy to use. All header based, no linking necessary.

Idiocyncracies/downsides:

  • API is quirky
    • what might be myVec.x() in another lib is only available via myVec[0] (Readability problem)
      • an array or stl::vector of points may cause you to do something like pointsList[0][0] to access the x component of the first point
    • in a naive attempt at optimization, removed cross(vec,vec) and replaced with makeCross(vec,vec,vec) when compiler eliminates unnecessary temps anyway
    • normal math operations don't return normal types unless you shut off some optimization features e.g.: vec1 - vec2 does not return a normal vector so length( vecA - vecB ) fails even though vecC = vecA - vecB works. You must wrap like: length( Vec( vecA - vecB ) )
    • operations on vectors are provided by external functions rather than members. This may require you to use the scope resolution everywhere since common symbol names may collide
    • you have to do
        length( makeCross( vecA, vecB ) )
      or
        gmtl::length( gmtl::makeCross( vecA, vecB ) )
      where otherwise you might try
        vecA.cross( vecB ).length()
  • not well maintained
    • still claimed as "beta"
    • documentation missing basic info like which headers are needed to use normal functionalty
      • Vec.h does not contain operations for Vectors, VecOps.h contains some, others are in Generate.h for example. cross(vec&,vec&,vec&) in VecOps.h, [make]cross(vec&,vec&) in Generate.h
  • immature/unstable API; still changing.
    • For example "cross" has moved from "VecOps.h" to "Generate.h", and then the name was changed to "makeCross". Documentation examples fail because still refer to old versions of functions that no-longer exist.

NT2

Can't tell because they seem to be more interested in the fractal image header of their web page than the content. Looks more like an academic project than a serious software project.

Latest release over 2 years ago.

Apparently no documentation in English though supposedly there is something in French somewhere.

Cant find a trace of a community around the project.

LAPACK & BLAS

Benefits: Old and mature.

Downsides:

  • old as dinosaurs with really crappy APIs
Catskul
  • 15,635
  • 13
  • 75
  • 111
  • 1
    Regarding the Eigen aligned asserts: to get high performance out of SSE(1,2,3 or 4) operations for small sets of data, you absolutely need aligned data. The unaligned load/store operations are much slower. The decision between aligned or unaligned load/store also takes time. Any "general purpose" implementation would have a really tough time doing the right thing for everyone, unless they separated the interface into "aligned" and "unaligned" operations as well - and then it's again simply not very general purpose. – Joris Timmermans Dec 15 '09 at 15:38
  • @Catskul I would like to use Eigen3. Could you please expand on "the optimizations which make it unsafe can be turned off with a define"? The other issues you list under Eigen2 are carefully detailed in the [doc](http://eigen.tuxfamily.org/dox-devel/) under *Topics related to alignment issues*. I can live with these issues. – Ali Dec 28 '12 at 15:27
  • The issues with safety I'm referring to all alignment related and are the same from the Eigen2. If you're ok with Eigen2, you'll be fine with Eigen3. – Catskul Dec 28 '12 at 19:41
  • 2
    BLAS and LAPACK aren't actually libraries but specifications/APIs. you could have mentioned their initial implementations by netlib or other implementations such as ATLAS and OpenBLAS. – Foad Feb 13 '17 at 20:13
12

For what it's worth, I've tried both Eigen and Armadillo. Below is a brief evaluation.

Eigen Advantages: 1. Completely self-contained -- no dependence on external BLAS or LAPACK. 2. Documentation decent. 3. Purportedly fast, although I haven't put it to the test.

Disadvantage: The QR algorithm returns just a single matrix, with the R matrix embedded in the upper triangle. No idea where the rest of the matrix comes from, and no Q matrix can be accessed.

Armadillo Advantages: 1. Wide range of decompositions and other functions (including QR). 2. Reasonably fast (uses expression templates), but again, I haven't really pushed it to high dimensions.

Disadvantages: 1. Depends on external BLAS and/or LAPACK for matrix decompositions. 2. Documentation is lacking IMHO (including the specifics wrt LAPACK, other than changing a #define statement).

Would be nice if an open source library were available that is self-contained and straightforward to use. I have run into this same issue for 10 years, and it gets frustrating. At one point, I used GSL for C and wrote C++ wrappers around it, but with modern C++ -- especially using the advantages of expression templates -- we shouldn't have to mess with C in the 21st century. Just my tuppencehapenny.

  • 2
    [Armadillo](http://arma.sourceforge.net) has a deliberate Matlab-like syntax, so that it is easy to use. I'm not sure what you mean about "documentation is lacking ... specifics wrt LAPACK". The documentation clearly documents all the user available functions, along with examples how to use them. The entire point about a C++ wrapper library is to abstract away the complexity and verbosity of LAPACK. You can always browse the source if you want to see how Armadillo calls LAPACK. – mtall Dec 18 '12 at 10:05
  • About the QR decomposition in Eigen, do you mean Eigen2 or Eigen3? – qed Jul 23 '13 at 07:51
11

If you are looking for high performance matrix/linear algebra/optimization on Intel processors, I'd look at Intel's MKL library.

MKL is carefully optimized for fast run-time performance - much of it based on the very mature BLAS/LAPACK fortran standards. And its performance scales with the number of cores available. Hands-free scalability with available cores is the future of computing and I wouldn't use any math library for a new project doesn't support multi-core processors.

Very briefly, it includes:

  1. Basic vector-vector, vector-matrix, and matrix-matrix operations
  2. Matrix factorization (LU decomp, hermitian,sparse)
  3. Least squares fitting and eigenvalue problems
  4. Sparse linear system solvers
  5. Non-linear least squares solver (trust regions)
  6. Plus signal processing routines such as FFT and convolution
  7. Very fast random number generators (mersenne twist)
  8. Much more.... see: link text

A downside is that the MKL API can be quite complex depending on the routines that you need. You could also take a look at their IPP (Integrated Performance Primitives) library which is geared toward high performance image processing operations, but is nevertheless quite broad.

Paul

CenterSpace Software ,.NET Math libraries, centerspace.net

Paul
  • 5,308
  • 1
  • 17
  • 18
8

I've heard good things about Eigen and NT2, but haven't personally used either. There's also Boost.UBLAS, which I believe is getting a bit long in the tooth. The developers of NT2 are building the next version with the intention of getting it into Boost, so that might count for somthing.

My lin. alg. needs don't exteed beyond the 4x4 matrix case, so I can't comment on advanced functionality; I'm just pointing out some options.

Jeff Hardy
  • 7,552
  • 22
  • 24
  • In my experience (larger matrices), Boost.UBLAS is used more. However, when I looked into it, I didn't like it (mainly because of the documentation) so I concentrated on Eigen. Eigen has a [geometry module](http://eigen.tuxfamily.org/dox-devel/group__Geometry__Module.html), but I haven't used it myself. – Jitse Niesen Sep 05 '09 at 11:39
  • Eigen is apparently used by ROS (willow garage), Celestia, Koffice, and libmv. I see some chatter about UBLAS, but had a hard time coming across project who advertise using it. Ditto for NT2. Can you elaborate on what good things you've heard? – Catskul Sep 09 '09 at 14:41
  • It was in a discussion on the Boost mailing list about adding a modern LinAlg library to Boost - Eigen and NT2 were both mentioned as possible candidates, but only the NT2 developers expressed interest in pursuing it. Both libraries seemed decent; as you said, Eigen is a little more popular, and also more C++-ish; NT2 is designed to mimic MATLAB as much as possible. – Jeff Hardy Sep 09 '09 at 17:47
8

I'm new to this topic, so I can't say a whole lot, but BLAS is pretty much the standard in scientific computing. BLAS is actually an API standard, which has many implementations. I'm honestly not sure which implementations are most popular or why.

If you want to also be able to do common linear algebra operations (solving systems, least squares regression, decomposition, etc.) look into LAPACK.

davidtbernal
  • 12,404
  • 9
  • 41
  • 58
8

What about GLM?

It's based on the OpenGL Shading Language (GLSL) specification and released under the MIT license. Clearly aimed at graphics programmers

user3742582
  • 103
  • 2
  • 5
  • 1
    well, it provide graphics programming vector and matrices. it introduces nice amount of overhead to keep compliant on GLSL (if you can do it in GLSL, most times doing it in GLSL is better especially with GL 4.x), and miss many graphics programming primitives (frustum, AABB, BB, ellipsoid). Its swizzle interface it's obese. Much better alternative would be if it had ".xyzz()" functions generated with some code generation. It is perfect when you have to prototype opengl applications and starts showing its negative sides on bigger projects. never code a math library. – CoffeDeveloper Apr 03 '15 at 14:01
6

I'll add vote for Eigen: I ported a lot of code (3D geometry, linear algebra and differential equations) from different libraries to this one - improving both performance and code readability in almost all cases.

One advantage that wasn't mentioned: it's very easy to use SSE with Eigen, which significantly improves performance of 2D-3D operations (where everything can be padded to 128 bits).

ima
  • 7,575
  • 3
  • 18
  • 19
  • 1
    The whole "if you do this then make sure to..." thing strikes me as a bit of a red flag. So far I've twice run into these issues and I just started using it. I really was hoping not to burden future developers for knowing all kinds of idiosyncrasies of each library included: specifically the alignment issues where it crashes if you dont use certain macros each time you have members, and the fact that they've spread functionality for individual classes across multiple headers. Alone it might not prevent me from choosing it, but it's sent up a bit of a red flag. – Catskul Sep 17 '09 at 15:21
  • 1
    Alignment and that macro only matters if you use SSE, which is by no means required. And if you do use SIMD, those issues will rise whatever library you use. At least Eigen doesn't just crash, but provides meaningful error messages which directly point to the problem. – ima Sep 18 '09 at 06:18
  • And there is an easy way to avoid alignment macro - use pointers or references as members. – ima Sep 18 '09 at 06:28
  • 1
    I dont think that is true. I used no special SSE options and got several crashes after using it with stl containers. Yes I know it gives you helpful messages, and Yes I know there are special instructions, but that's my point. I dont want to burden other developers with special instructions for each included library. The don't pass by value thing for example is just too much. – Catskul Sep 21 '09 at 04:14
  • I just found out that the latest development branch has some defines you can use to turn off the alignment and avoid the related issues. – Catskul Sep 21 '09 at 05:43
4

Okay, I think I know what you're looking for. It appears that GGT is a pretty good solution, as Reed Copsey suggested.

Personally, we rolled our own little library, because we deal with rational points a lot - lots of rational NURBS and Beziers.

It turns out that most 3D graphics libraries do computations with projective points that have no basis in projective math, because that's what gets you the answer you want. We ended up using Grassmann points, which have a solid theoretical underpinning and decreased the number of point types. Grassmann points are basically the same computations people are using now, with the benefit of a robust theory. Most importantly, it makes things clearer in our minds, so we have fewer bugs. Ron Goldman wrote a paper on Grassmann points in computer graphics called "On the Algebraic and Geometric Foundations of Computer Graphics".

Not directly related to your question, but an interesting read.

tfinniga
  • 6,404
  • 3
  • 29
  • 36
  • It's intentionally open-ended in that I'm unaware of what the trade-off's are. It's probably fair to say that geometry is our main concern the dimensionality of the geometry is not clear. Currently it is 2/3 (2 + time) and could hypothetically be quite high (3dims + time + multi-dim-costmaps). – Catskul Sep 04 '09 at 17:15
  • I'm in agreement with the question. For instance, a lot of applications of this sort need realtime (consistent time behavior) performance, while many others are just fine giving up consistency and/or speed for accuracy. – T.E.D. Sep 04 '09 at 17:34
  • So are you saying that of the libraries you investigated, none took care of NURBS and Beziers? Any particular reason for not taking one of the existing libraries and building the NURBS and Bezier support in along side of it? – Catskul Sep 09 '09 at 14:40
  • What I was trying to say is that rational NURBS and Beziers use rational control points much more than most 3d applications, so we were making more mistakes. Typically most 3d apps only have vanilla 3d points and vectors until after going through the perspective transform. Many of our algorithms have to be able to correctly handle weighted/rational/projective and cartesian points, going back and forth, etc. – tfinniga Sep 09 '09 at 18:49
0

FLENS

http://flens.sf.net

It also implements a lot of LAPACK functions.

Michael Lehn
  • 2,347
  • 2
  • 13
  • 19
0

I found this library quite simple and functional (http://kirillsprograms.com/top_Vectors.php). These are bare bone vectors implemented via C++ templates. No fancy stuff - just what you need to do with vectors (add, subtract multiply, dot, etc).