Mentions légales du service

Skip to content
Snippets Groups Projects
Commit f342cb1f authored by hhakim's avatar hhakim
Browse files

Add to matfaust eigtj/fgft_givens an order argument to define the eigenvalues sort.

parent 9dc07208
No related branches found
No related tags found
No related merge requests found
...@@ -69,6 +69,7 @@ namespace Faust { ...@@ -69,6 +69,7 @@ namespace Faust {
Faust::Vect<FPP,DEVICE> ordered_D; Faust::Vect<FPP,DEVICE> ordered_D;
/** \brief true if D has already been ordered (order_D() was called). */ /** \brief true if D has already been ordered (order_D() was called). */
bool is_D_ordered; bool is_D_ordered;
int D_order_dir;
/** \brief The level of verbosity (0 for nothing, 1 for iteration numbers,...) */ /** \brief The level of verbosity (0 for nothing, 1 for iteration numbers,...) */
unsigned int verbosity; unsigned int verbosity;
...@@ -196,10 +197,18 @@ namespace Faust { ...@@ -196,10 +197,18 @@ namespace Faust {
void update_err(); void update_err();
/** /**
* Order D into ordered_D and keeps ordered indices in ord_indices. * Order (sort) D ascendantly into ordered_D and keeps ordered indices in ord_indices.
*/ */
void order_D(); void order_D();
/**
* Order D into ascendantly or descendantly into order_D and keeps ordered indices in ord_indices.
*
* \param order -1 to order descendantly, 1 to order ascendantly.
*/
void order_D(int order);
public: public:
/** /**
...@@ -225,6 +234,12 @@ namespace Faust { ...@@ -225,6 +234,12 @@ namespace Faust {
*/ */
const Faust::Vect<FPP,DEVICE>& get_D(const bool ord=false); const Faust::Vect<FPP,DEVICE>& get_D(const bool ord=false);
/**
* \param ord 0 (no sort), 1 (ascendant sort), -1 (descendant sort).
*/
const Faust::Vect<FPP,DEVICE>& get_D(const int ord=0);
/** \brief Returns the diagonal vector as a sparse matrix. /** \brief Returns the diagonal vector as a sparse matrix.
* *
* \note This function makes copies, is not intented for repeated use (use get_D() for optimized calls). * \note This function makes copies, is not intented for repeated use (use get_D() for optimized calls).
...@@ -239,6 +254,12 @@ namespace Faust { ...@@ -239,6 +254,12 @@ namespace Faust {
*/ */
void get_D(FPP* diag_data, const bool ord=false); void get_D(FPP* diag_data, const bool ord=false);
/**
*
* \param ord: 0 for no sort, -1 for descending order, 1 for descending order.
*/
void get_D(FPP* diag_data, const int ord=0);
/** /**
* Computes and returns the Fourier matrix approximate from the Givens factors computed up to this time. * Computes and returns the Fourier matrix approximate from the Givens factors computed up to this time.
...@@ -283,6 +304,10 @@ namespace Faust { ...@@ -283,6 +304,10 @@ namespace Faust {
* \param ord true to get the Transform's facts ordering the last one columns according to ascendant eigenvalues, false to let facts as they went out from the algorithm (without reordering). * \param ord true to get the Transform's facts ordering the last one columns according to ascendant eigenvalues, false to let facts as they went out from the algorithm (without reordering).
*/ */
Faust::Transform<FPP,DEVICE> get_transform(bool ord); Faust::Transform<FPP,DEVICE> get_transform(bool ord);
/**
* \param ord -1 for descending order, 1 for ascending order.
*/
Faust::Transform<FPP,DEVICE> get_transform(int ord);
}; };
......
...@@ -402,17 +402,24 @@ void GivensFGFT<FPP,DEVICE,FPP2>::update_err() ...@@ -402,17 +402,24 @@ void GivensFGFT<FPP,DEVICE,FPP2>::update_err()
template<typename FPP, Device DEVICE, typename FPP2> template<typename FPP, Device DEVICE, typename FPP2>
void GivensFGFT<FPP,DEVICE,FPP2>::order_D() void GivensFGFT<FPP,DEVICE,FPP2>::order_D()
{
order_D(1);
}
template<typename FPP, Device DEVICE, typename FPP2>
void GivensFGFT<FPP,DEVICE,FPP2>::order_D(const int order /* -1 for descending order, 1 for ascending order */)
{ {
ordered_D = Faust::Vect<FPP,DEVICE>(D.size()); ordered_D = Faust::Vect<FPP,DEVICE>(D.size());
ord_indices.resize(0); ord_indices.resize(0);
for(int i=0;i<D.size();i++) for(int i=0;i<D.size();i++)
ord_indices.push_back(i); ord_indices.push_back(i);
sort(ord_indices.begin(), ord_indices.end(), [this](int i, int j) { sort(ord_indices.begin(), ord_indices.end(), [this, &order](int i, int j) {
return D.getData()[i] < D.getData()[j]; return order>0?D.getData()[i] < D.getData()[j]:D.getData()[i] > D.getData()[j];
}); });
for(int i=0;i<ord_indices.size();i++) for(int i=0;i<ord_indices.size();i++)
ordered_D.getData()[i] = D.getData()[ord_indices[i]]; ordered_D.getData()[i] = D.getData()[ord_indices[i]];
is_D_ordered = true; is_D_ordered = true;
D_order_dir = order;
} }
template<typename FPP, Device DEVICE, typename FPP2> template<typename FPP, Device DEVICE, typename FPP2>
...@@ -528,7 +535,18 @@ const Faust::Vect<FPP,DEVICE>& GivensFGFT<FPP,DEVICE,FPP2>::get_D(const bool ord ...@@ -528,7 +535,18 @@ const Faust::Vect<FPP,DEVICE>& GivensFGFT<FPP,DEVICE,FPP2>::get_D(const bool ord
if(!is_D_ordered) if(!is_D_ordered)
order_D(); order_D();
return ordered_D; return ordered_D;
}
return D;
}
template<typename FPP, Device DEVICE, typename FPP2>
const Faust::Vect<FPP,DEVICE>& GivensFGFT<FPP,DEVICE,FPP2>::get_D(const int ord /* default to false */)
{
if(ord != 0)
{
if(!is_D_ordered || ord != D_order_dir)
order_D(ord);
return ordered_D;
} }
return D; return D;
} }
...@@ -550,13 +568,18 @@ const Faust::MatSparse<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::get_Dspm(const b ...@@ -550,13 +568,18 @@ const Faust::MatSparse<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::get_Dspm(const b
template<typename FPP, Device DEVICE, typename FPP2> template<typename FPP, Device DEVICE, typename FPP2>
void GivensFGFT<FPP,DEVICE,FPP2>::get_D(FPP* diag_data, const bool ord /* default to false */) void GivensFGFT<FPP,DEVICE,FPP2>::get_D(FPP* diag_data, const bool ord /* default to false */)
{
get_D(diag_data, ord?1:0);
}
template<typename FPP, Device DEVICE, typename FPP2>
void GivensFGFT<FPP,DEVICE,FPP2>::get_D(FPP* diag_data, const int ord /* default to false */)
{ {
const Faust::Vect<FPP,DEVICE>& D_ = get_D(ord); const Faust::Vect<FPP,DEVICE>& D_ = get_D(ord);
const FPP* src_data_ptr = D_.getData(); const FPP* src_data_ptr = D_.getData();
memcpy(diag_data, src_data_ptr, sizeof(FPP)*D_.size()); memcpy(diag_data, src_data_ptr, sizeof(FPP)*D_.size());
} }
template<typename FPP, Device DEVICE, typename FPP2> template<typename FPP, Device DEVICE, typename FPP2>
const Faust::MatDense<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::compute_fourier(const bool ord /* default to false */) const Faust::MatDense<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::compute_fourier(const bool ord /* default to false */)
{ {
...@@ -615,13 +638,20 @@ const vector<Faust::MatSparse<FPP,DEVICE>>& GivensFGFT<FPP,DEVICE,FPP2>::get_fac ...@@ -615,13 +638,20 @@ const vector<Faust::MatSparse<FPP,DEVICE>>& GivensFGFT<FPP,DEVICE,FPP2>::get_fac
template<typename FPP, Device DEVICE, typename FPP2> template<typename FPP, Device DEVICE, typename FPP2>
Faust::Transform<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::get_transform(bool ord) Faust::Transform<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::get_transform(bool ord)
{
return get_transform(ord?1:0);
}
template<typename FPP, Device DEVICE, typename FPP2>
Faust::Transform<FPP,DEVICE> GivensFGFT<FPP,DEVICE,FPP2>::get_transform(int ord)
{ {
//TODO: an optimization is possible by changing type of facts to vector<MatGeneric*> it would avoid copying facts into Transform and rather use them directly. It will need a destructor that deletes them eventually if they weren't transfered to a Transform object before. //TODO: an optimization is possible by changing type of facts to vector<MatGeneric*> it would avoid copying facts into Transform and rather use them directly. It will need a destructor that deletes them eventually if they weren't transfered to a Transform object before.
if(ord) if(ord)
{ {
// add a permutation factor to reorder according to ordered D // add a permutation factor to reorder according to ordered D
if(!is_D_ordered) if(ord != 0 && (!is_D_ordered || ord != D_order_dir))
order_D(); order_D(ord);
MatSparse<FPP,DEVICE> & last_fact = *(facts.end()-1); MatSparse<FPP,DEVICE> & last_fact = *(facts.end()-1);
MatSparse<FPP,DEVICE> P(last_fact.getNbCol(), last_fact.getNbCol()); //last_fact is a sqr. mat. MatSparse<FPP,DEVICE> P(last_fact.getNbCol(), last_fact.getNbCol()); //last_fact is a sqr. mat.
P.set_orthogonal(true); P.set_orthogonal(true);
......
...@@ -22,11 +22,12 @@ ...@@ -22,11 +22,12 @@
%> @param 'relerr', true (optional) For a stopping criterion based on the relative squared error (this is the default error). %> @param 'relerr', true (optional) For a stopping criterion based on the relative squared error (this is the default error).
%> @param 'relerr', false (optional) For a stopping criterion based on the absolute squared error. %> @param 'relerr', false (optional) For a stopping criterion based on the absolute squared error.
%> @param 'verbosity', integer (optional) the level of verbosity, the greater the value the more info. is displayed. %> @param 'verbosity', integer (optional) the level of verbosity, the greater the value the more info. is displayed.
%> @param 'order', integer (optional) -1 for a descending order of eigenvalues, 1 for an ascending order.
%> %>
%> @retval [V,D] %> @retval [V,D]
%> - V the Faust object representing the approximate eigenvector transform. The column V(:, i) is the eigenvector corresponding to the eigenvalue D(i,i). %> - V the Faust object representing the approximate eigenvector transform. The column V(:, i) is the eigenvector corresponding to the eigenvalue D(i,i).
%> The last factor of V is a permutation matrix. The goal of this factor is to apply to the columns of V the same order as eigenvalues set in D. %> The last factor of V is a permutation matrix. The goal of this factor is to apply to the columns of V the same order as eigenvalues set in D.
%> - D the approximate sparse diagonal matrix of the eigenvalues (in ascendant order along the rows/columns). %> - D the approximate sparse diagonal matrix of the eigenvalues (by default in ascendant order along the rows/columns).
%> %>
%> @b Example %> @b Example
%> @code %> @code
......
...@@ -11,10 +11,11 @@ ...@@ -11,10 +11,11 @@
%> @param 'tol', number see fact.eigtj %> @param 'tol', number see fact.eigtj
%> @param 'relerr', bool see fact.eigtj %> @param 'relerr', bool see fact.eigtj
%> @param 'verbosity', integer see fact.eigtj %> @param 'verbosity', integer see fact.eigtj
%> @param 'order', integer see fact.eigtj
%> %>
%> @retval [FGFT,D]: %> @retval [FGFT,D]:
%> - with FGFT being the Faust object representing the Fourier transform and, %> - with FGFT being the Faust object representing the Fourier transform and,
%> - D as a sparse diagonal matrix of the eigenvalues in ascendant order along the rows/columns. %> - D as a sparse diagonal matrix of the eigenvalues by default in ascendant order along the rows/columns.
%> %>
%> %>
%> @b References: %> @b References:
...@@ -45,6 +46,7 @@ function [FGFT,D] = fgft_givens(Lap, maxiter, varargin) ...@@ -45,6 +46,7 @@ function [FGFT,D] = fgft_givens(Lap, maxiter, varargin)
relerr = true; relerr = true;
verbosity = 0; verbosity = 0;
argc = length(varargin); argc = length(varargin);
order = 1; % ascending order
if(argc > 0) if(argc > 0)
for i=1:argc for i=1:argc
switch(varargin{i}) switch(varargin{i})
...@@ -52,27 +54,33 @@ function [FGFT,D] = fgft_givens(Lap, maxiter, varargin) ...@@ -52,27 +54,33 @@ function [FGFT,D] = fgft_givens(Lap, maxiter, varargin)
if(argc == i || ~ isscalar(varargin{i+1})) if(argc == i || ~ isscalar(varargin{i+1}))
error('tol keyword arg. is not followed by a number') error('tol keyword arg. is not followed by a number')
else else
tol = real(varargin{i+1}) % real in case of cplx num tol = real(varargin{i+1}); % real in case of cplx num
end end
case 'relerr' case 'relerr'
if(argc == i || ~ islogical(varargin{i+1})) if(argc == i || ~ islogical(varargin{i+1}))
error('relerr keyword argument is not followed by a logical') error('relerr keyword argument is not followed by a logical')
else else
relerr = varargin{i+1} relerr = varargin{i+1};
end end
case 'verbosity' case 'verbosity'
if(argc == i || ~ isscalar(varargin{i+1})) if(argc == i || ~ isscalar(varargin{i+1}))
error('verbose keyword argument is not followed by a number') error('verbose keyword argument is not followed by a number')
else else
verbosity = floor(real(varargin{i+1})) verbosity = floor(real(varargin{i+1}));
end end
case 'nGivens_per_fac' case 'nGivens_per_fac'
if(argc == i || ~ isscalar(varargin{i+1}) || ~ isnumeric(nGivens_per_fac)) if(argc == i || ~ isscalar(varargin{i+1}) || ~ isnumeric(varargin{i+1}))
error('nGivens_per_fac must be followed by a positive integer.') error('nGivens_per_fac must be followed by a positive integer.')
else else
nGivens_per_fac = floor(abs(real(varargin{i+1}))); nGivens_per_fac = floor(abs(real(varargin{i+1})));
nGivens_per_fac = min(nGivens_per_fac, maxiter); nGivens_per_fac = min(nGivens_per_fac, maxiter);
nGivens_per_fac = max(1, nGivens_per_fac) nGivens_per_fac = max(1, nGivens_per_fac);
end
case 'order'
if(argc == i || ~ isscalar(varargin{i+1}) || ~ isnumeric(varargin{i+1}))
error('order must be followed by an integer.')
else
order = varargin{i+1};
end end
otherwise otherwise
if(isstr(varargin{i})) if(isstr(varargin{i}))
...@@ -81,7 +89,7 @@ function [FGFT,D] = fgft_givens(Lap, maxiter, varargin) ...@@ -81,7 +89,7 @@ function [FGFT,D] = fgft_givens(Lap, maxiter, varargin)
end end
end end
end end
[core_obj, D] = mexfgftgivensReal(Lap, maxiter, nGivens_per_fac, verbosity, tol, relerr); [core_obj, D] = mexfgftgivensReal(Lap, maxiter, nGivens_per_fac, verbosity, tol, relerr, order);
D = sparse(diag(D)); D = sparse(diag(D));
FGFT = Faust(core_obj, true); FGFT = Faust(core_obj, true);
end end
...@@ -59,8 +59,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) ...@@ -59,8 +59,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
unsigned int verbosity = 0; //default verbosity (no info. displayed) unsigned int verbosity = 0; //default verbosity (no info. displayed)
double tol = 0; double tol = 0;
bool relErr = true; bool relErr = true;
int order;
if(nrhs < 2 || nrhs > 6) if(nrhs < 2 || nrhs > 7)
mexErrMsgTxt("Bad Number of inputs arguments"); mexErrMsgTxt("Bad Number of inputs arguments");
J = (int) mxGetScalar(prhs[1]); J = (int) mxGetScalar(prhs[1]);
...@@ -72,6 +73,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) ...@@ -72,6 +73,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
tol = (double) mxGetScalar(prhs[4]); tol = (double) mxGetScalar(prhs[4]);
if(nrhs >= 6) if(nrhs >= 6)
relErr = (bool) mxGetScalar(prhs[5]); relErr = (bool) mxGetScalar(prhs[5]);
if(nrhs >= 7)
order = (int) mxGetScalar(prhs[6]); //eigenvalues order
const mxArray* matlab_matrix = prhs[0]; // Laplacian const mxArray* matlab_matrix = prhs[0]; // Laplacian
...@@ -112,11 +115,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) ...@@ -112,11 +115,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
Faust::Vect<SCALAR,Cpu> D(Lap->getNbRow()); Faust::Vect<SCALAR,Cpu> D(Lap->getNbRow());
// true below is for ascendant order of eigenvalues // true below is for ascendant order of eigenvalues
algo->get_D(const_cast<SCALAR*>(D.getData()), true); // don't respect constness for optimization (saving a vector copy) algo->get_D(const_cast<SCALAR*>(D.getData()), order); // don't respect constness for optimization (saving a vector copy)
plhs[1] = FaustVec2mxArray(D); plhs[1] = FaustVec2mxArray(D);
Faust::Transform<SCALAR,Cpu> trans = std::move(algo->get_transform(true)); // true for same order of "eigenvectors" as eigenvalues Faust::Transform<SCALAR,Cpu> trans = std::move(algo->get_transform(order)); // true for same order of "eigenvectors" as eigenvalues
TransformHelper<SCALAR,Cpu> *th = new TransformHelper<SCALAR,Cpu>(trans, true); // true is for moving and not copying the Transform object into TransformHelper (optimization possible cause we know the original object won't be used later) TransformHelper<SCALAR,Cpu> *th = new TransformHelper<SCALAR,Cpu>(trans, true); // true is for moving and not copying the Transform object into TransformHelper (optimization possible cause we know the original object won't be used later)
plhs[0] = convertPtr2Mat<Faust::TransformHelper<SCALAR, Cpu>>(th); plhs[0] = convertPtr2Mat<Faust::TransformHelper<SCALAR, Cpu>>(th);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment