Of course this is not a bug, since checks like this one is all over uBLAS. I guess this is because most of its operations would make no sense for non-float types.
You can disable type checks using
#define BOOST_UBLAS_TYPE_CHECK 0
before includes. But think twice! Take a look at example
#include <iostream>
#define BOOST_UBLAS_TYPE_CHECK 0
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/lu.hpp>
namespace ublas = boost::numeric::ublas;
template<typename ValType>
ValType det_fast(const ublas::matrix<ValType>& matrix)
{
// create a working copy of the input
ublas::matrix<ValType> mLu(matrix);
ublas::permutation_matrix<std::size_t> pivots(matrix.size1());
auto isSingular = ublas::lu_factorize(mLu, pivots);
if (isSingular)
return static_cast<ValType>(0);
ValType det = static_cast<ValType>(1);
for (std::size_t i = 0; i < pivots.size(); ++i)
{
if (pivots(i) != i)
det *= static_cast<ValType>(-1);
det *= mLu(i, i);
}
return det;
}
int main()
{
ublas::matrix<int> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
std::cout << det_fast(m) << std::endl;
}
It is obvious that matrix m
is singular, and if you change type from int
to double
functions returns zero. But with int
it returns -48
.
EDIT #1
Also, you can create ublas::matrix<int>
without any errors and assign it to ublas::matrix<float>
. So one way to correctly calculate determinant is to overload det_fast
and remove define
statement.
int det_fast(const ublas::matrix<int>& matrix)
{
return (int)det_fast(ublas::matrix<float>(matrix));
}
EDIT #2
Take a look at the table, where average time
is time of full determinant calculation (for int
with copy operation) of 5 program runs.
size | average time, ms
------------------------
| int float
------------------------
100 | 9.0 9.0
200 | 46.6 46.8
300 | 156.4 159.4
400 | 337.4 331.4
500 | 590.8 609.2
600 | 928.2 1009.4
700 | 1493.8 1525.2
800 | 2162.8 2231.0
900 | 3184.2 3025.2
You might think that for int
it is faster, but it's not true. In average for more runs I'm sure that you will get slight acceleration with float
(I guess about 0-15 ms, which is time measure error). Also if we measure copy time we will see, that for matrix size less than 3000 x 3000 it is near zero (it is also about 0-15 ms, which is time measure error). For larger matrices copy time increases (for example for 5000 x 5000 matrix it is 125 ms). But there is one important note! Copy time is less than 1.0% of all determinant calculation for int
type matrix and it is greatly decreasing with size grow!
All of this measures were made for a program compiled with Visual Studio 2013 in release configuration with boost version 1.58. Time were measured with clock
function. CPU is Intel Xeon E5645 2.4GHz.
Also perfomance mostly depends on how your methods will be used. If you're going to call this function many times for small matrices than the copy time may become significant.