diff --git a/misc/test/src/Python/test_FaustPy.py b/misc/test/src/Python/test_FaustPy.py index 1dad4bf12ceb9196a076a8be27a7d7cb80985f40..4e5a63137696ac551b4c5e1f8ad2cf67a28fd405 100644 --- a/misc/test/src/Python/test_FaustPy.py +++ b/misc/test/src/Python/test_FaustPy.py @@ -906,7 +906,7 @@ class TestFaustFactory(unittest.TestCase): L = L.astype(np.float64) J = \ int(loadmat(sys.path[0]+"/../../../misc/data/mat/test_GivensDiag_Lap_U_J.mat")['J']) - F, D = pyfaust.fact.fgft_givens(L, J, 0, verbosity=0) + F, D = pyfaust.fact.fgft_givens(L, J, nGivens_per_fac=1, verbosity=0) print("Lap norm:", norm(L, 'fro')) err = norm((F*D.todense())*F.T.todense()-L,"fro")/norm(L,"fro") print("err: ", err) @@ -922,14 +922,14 @@ class TestFaustFactory(unittest.TestCase): J = \ int(loadmat(sys.path[0]+"/../../../misc/data/mat/test_GivensDiag_Lap_U_J.mat")['J']) t = int(L.shape[0]/2) - F, D = fgft_givens(L, J, t, verbosity=0) + F, D = fgft_givens(L, J, nGivens_per_fac=t, verbosity=0) print("Lap norm:", norm(L, 'fro')) err = norm((F*D.todense())*F.T.todense()-L,"fro")/norm(L,"fro") print("err: ", err) # the error reference is from the C++ test, # misc/test/src/C++/GivensFGFTParallel.cpp.in self.assertAlmostEqual(err, 0.0410448, places=7) - F2, D2 = eigtj(L, J, t, verbosity=0) + F2, D2 = eigtj(L, J, nGivens_per_fac=t, verbosity=0) print("Lap norm:", norm(L, 'fro')) err2 = norm((F2*D.todense())*F2.T.todense()-L,"fro")/norm(L,"fro") print("err2: ", err2) @@ -946,7 +946,7 @@ class TestFaustFactory(unittest.TestCase): L = L.astype(np.float64) J = \ int(loadmat(sys.path[0]+"/../../../misc/data/mat/test_GivensDiag_Lap_U_J.mat")['J']) - F, D = pyfaust.fact.fgft_givens(csr_matrix(L), J, 0, verbosity=0) + F, D = pyfaust.fact.fgft_givens(csr_matrix(L), J, nGivens_per_fac=0, verbosity=0) print("Lap norm:", norm(L, 'fro')) err = norm((F*D.todense())*F.T.todense()-L,"fro")/norm(L,"fro") print("err: ", err) @@ -955,7 +955,7 @@ class TestFaustFactory(unittest.TestCase): self.assertAlmostEqual(err, 0.0326529, places=7) def testFGFTGivensParallelSparse(self): - print("Test pyfaust.fact.fgft_givens() -- parallel") + print("Test pyfaust.fact.fgft_givens_sparse() -- parallel") from pyfaust.fact import eigtj, fgft_givens from scipy.sparse import csr_matrix L = loadmat(sys.path[0]+"/../../../misc/data/mat/test_GivensDiag_Lap_U_J.mat")['Lap'] @@ -963,14 +963,14 @@ class TestFaustFactory(unittest.TestCase): J = \ int(loadmat(sys.path[0]+"/../../../misc/data/mat/test_GivensDiag_Lap_U_J.mat")['J']) t = int(L.shape[0]/2) - F, D = fgft_givens(csr_matrix(L), J, t, verbosity=0) + F, D = fgft_givens(csr_matrix(L), J, nGivens_per_fac=t, verbosity=0) print("Lap norm:", norm(L, 'fro')) err = norm((F*D.todense())*F.T.todense()-L,"fro")/norm(L,"fro") print("err: ", err) # the error reference is from the C++ test, # misc/test/src/C++/GivensFGFTParallel.cpp.in self.assertAlmostEqual(err, 0.0410448, places=7) - F2, D2 = eigtj(L, J, t, verbosity=0) + F2, D2 = eigtj(L, J, nGivens_per_fac=t, verbosity=0) print("Lap norm:", norm(L, 'fro')) err2 = norm((F2*D.todense())*F2.T.todense()-L,"fro")/norm(L,"fro") print("err2: ", err2) diff --git a/src/algorithm/factorization/faust_GivensFGFT.h b/src/algorithm/factorization/faust_GivensFGFT.h index 85fffec2919c47a87983b600df9e7a206044e595..073e800fcad25c549add5931b484004ada8fb872 100644 --- a/src/algorithm/factorization/faust_GivensFGFT.h +++ b/src/algorithm/factorization/faust_GivensFGFT.h @@ -35,6 +35,7 @@ namespace Faust { /** \brief Pivot candidates q coordinates. */ int* q_candidates; /* default IndexType for underlying eigen matrix is int. */ protected: + const static unsigned int ERROR_CALC_PERIOD = 100; /** \brief Fourier matrix factorization matrices (Givens matrix). */ vector<Faust::MatSparse<FPP,DEVICE>> facts; /** \brief Diagonalization approximate of Laplacian. */ @@ -88,6 +89,10 @@ namespace Faust { /** \brief In calc_theta() two values are calculated for theta, this boolean is set to true to always choose theta2 (useful for GivensFGFTParallel). */ bool always_theta2; + bool stoppingCritIsError; + double stoppingError; + bool errIsRel; + /** * Function pointer to any step of the algorithm (internal purpose only). */ @@ -100,8 +105,8 @@ namespace Faust { * \param Lap The Laplacian matrix to approximate/diagonalize. * \param J The number of iterations, Givens rotations factors. * */ - GivensFGFT(Faust::MatSparse<FPP,DEVICE>& Lap, int J, unsigned int verbosity = 0); - GivensFGFT(Faust::MatDense<FPP,DEVICE>& Lap, int J, unsigned int verbosity = 0); + GivensFGFT(Faust::MatSparse<FPP,DEVICE>& Lap, int J, unsigned int verbosity = 0, const double stoppingError = 0.0, const bool errIsRel = true); + GivensFGFT(Faust::MatDense<FPP,DEVICE>& Lap, int J, unsigned int verbosity = 0, const double stoppingError = 0.0, const bool errIsRel = true); /** Destructor */ virtual ~GivensFGFT() {delete[] q_candidates; delete L;}; diff --git a/src/algorithm/factorization/faust_GivensFGFT.hpp b/src/algorithm/factorization/faust_GivensFGFT.hpp index 55aada53957dfbe878c9023331ec4f112a447065..3bf3bc78d50f5c03282eb1de54115c9c6766af57 100644 --- a/src/algorithm/factorization/faust_GivensFGFT.hpp +++ b/src/algorithm/factorization/faust_GivensFGFT.hpp @@ -371,7 +371,7 @@ void GivensFGFT<FPP,DEVICE,FPP2>::update_err() // % disp(['Number of edges: ' num2str(N_edges)]) // end // - if(!((ite+1)%100) || verbosity > 1) + if(!((ite+1)%GivensFGFT<FPP,DEVICE,FPP2>::ERROR_CALC_PERIOD) || stoppingCritIsError || verbosity > 1) { MatDense<FPP,DEVICE> tmp = this->get_Dspm(false); MatDense<FPP,DEVICE>* dL; @@ -388,11 +388,14 @@ void GivensFGFT<FPP,DEVICE,FPP2>::update_err() } FPP2 err = tmp.norm(), err_d; err *= err; - err_d = Lap.norm(); - err_d *= err_d; - err /= err_d; + if(errIsRel) + { + err_d = Lap.norm(); + err_d *= err_d; + err /= err_d; + } if(verbosity) - cout << "GivensFGFT ite. i: "<< ite << " err.: " << err << endl; + cout << "GivensFGFT factor : "<< ite << ", transform " << ((errIsRel)?"relative ":"absolute ") << "err.: " << err << endl; errs.push_back(err); } } @@ -430,11 +433,16 @@ void GivensFGFT<FPP,DEVICE,FPP2>::compute_facts() { next_step(); ite++; + if(stoppingCritIsError && *(errs.end()-1) <= stoppingError) + { + facts.resize(ite); + break; + } } } template<typename FPP, Device DEVICE, typename FPP2> -GivensFGFT<FPP,DEVICE,FPP2>::GivensFGFT(Faust::MatSparse<FPP,DEVICE>& Lap, int J, unsigned int verbosity /* deft val == 0 */) : Lap(Lap), facts(J), D(Lap.getNbRow()), C(Lap.getNbRow(), Lap.getNbCol()), errs(0), coord_choices(J), q_candidates(new int[Lap.getNbCol()]), is_D_ordered(false), always_theta2(false), verbosity(verbosity) +GivensFGFT<FPP,DEVICE,FPP2>::GivensFGFT(Faust::MatSparse<FPP,DEVICE>& Lap, int J, unsigned int verbosity /* deft val == 0 */, const double stopingError /* default to 0.0 */, const bool errIsRel) : Lap(Lap), facts(J), D(Lap.getNbRow()), C(Lap.getNbRow(), Lap.getNbCol()), errs(0), coord_choices(J), q_candidates(new int[Lap.getNbCol()]), is_D_ordered(false), always_theta2(false), verbosity(verbosity), stoppingCritIsError(stoppingError != 0.0), stoppingError(stoppingError), errIsRel(errIsRel) { /* Matlab ref. code: * facts = cell(1,J); @@ -466,7 +474,7 @@ GivensFGFT<FPP,DEVICE,FPP2>::GivensFGFT(Faust::MatSparse<FPP,DEVICE>& Lap, int J } template<typename FPP, Device DEVICE, typename FPP2> -GivensFGFT<FPP,DEVICE,FPP2>::GivensFGFT(Faust::MatDense<FPP,DEVICE>& Lap, int J, unsigned int verbosity /* deft val == 0 */) : Lap(Lap), facts(J), D(Lap.getNbRow()), C(Lap.getNbRow(), Lap.getNbCol()), errs(0), coord_choices(J), q_candidates(new int[Lap.getNbCol()]), is_D_ordered(false), always_theta2(false), verbosity(verbosity) +GivensFGFT<FPP,DEVICE,FPP2>::GivensFGFT(Faust::MatDense<FPP,DEVICE>& Lap, int J, unsigned int verbosity /* deft val == 0 */, const double stoppingError, const bool errIsRel) : Lap(Lap), facts(J), D(Lap.getNbRow()), C(Lap.getNbRow(), Lap.getNbCol()), errs(0), coord_choices(J), q_candidates(new int[Lap.getNbCol()]), is_D_ordered(false), always_theta2(false), verbosity(verbosity), stoppingCritIsError(stoppingError != 0.0), stoppingError(stoppingError), errIsRel(errIsRel) { /* Matlab ref. code: * facts = cell(1,J); diff --git a/src/algorithm/factorization/faust_GivensFGFTParallel.h b/src/algorithm/factorization/faust_GivensFGFTParallel.h index 34d2eb761b40b974c08f24746c1d6939fe612a5f..8e51c7f426973ebef5dbbb52cca5ed309b88a1ac 100644 --- a/src/algorithm/factorization/faust_GivensFGFTParallel.h +++ b/src/algorithm/factorization/faust_GivensFGFTParallel.h @@ -81,10 +81,11 @@ namespace Faust { * \param Lap The Laplacian matrix to approximate/diagonalize. * \param J round(J/t) is the number of factors to approximate the Fourier matrix (as a product of factors). * \param t the maximum number of 2D rotation matrices (Givens matrices) to insert in each factor. The effective number can be less than t if there is not enough pivot candidates left in the matrix L of the current iteration. + * \param stoppingError defines a stopping criterion based on error (absolute relative error). * */ - GivensFGFTParallel(Faust::MatDense<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity = 0); - GivensFGFTParallel(Faust::MatSparse<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity = 0); + GivensFGFTParallel(Faust::MatDense<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity = 0, const double stoppingCritIsError = 0.0, const bool errIsRel = true); + GivensFGFTParallel(Faust::MatSparse<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity = 0, const double stoppingCritIsError = 0.0, const bool errIsRel = true); }; diff --git a/src/algorithm/factorization/faust_GivensFGFTParallel.hpp b/src/algorithm/factorization/faust_GivensFGFTParallel.hpp index 56eacdc99db052e96db7dca5f214f485c72cf922..46a7388ea7b1715f8d5b93d9dff14fc24d7eb2ca 100644 --- a/src/algorithm/factorization/faust_GivensFGFTParallel.hpp +++ b/src/algorithm/factorization/faust_GivensFGFTParallel.hpp @@ -6,7 +6,7 @@ using namespace Faust; #endif template<typename FPP, Device DEVICE, typename FPP2> -GivensFGFTParallel<FPP,DEVICE,FPP2>::GivensFGFTParallel(Faust::MatDense<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity) : GivensFGFT<FPP,DEVICE,FPP2>(Lap, J, verbosity), t(t), fact_nrots(0) +GivensFGFTParallel<FPP,DEVICE,FPP2>::GivensFGFTParallel(Faust::MatDense<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity, const double stoppingError, const bool errIsRel) : GivensFGFT<FPP,DEVICE,FPP2>(Lap, J, verbosity, stoppingError, errIsRel), t(t), fact_nrots(0) { this->facts.resize(round(J/(float)t)); this->always_theta2 = true; @@ -14,7 +14,7 @@ GivensFGFTParallel<FPP,DEVICE,FPP2>::GivensFGFTParallel(Faust::MatDense<FPP,DEVI } template<typename FPP, Device DEVICE, typename FPP2> -GivensFGFTParallel<FPP,DEVICE,FPP2>::GivensFGFTParallel(Faust::MatSparse<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity) : GivensFGFT<FPP,DEVICE,FPP2>(Lap, J, verbosity), t(t), fact_nrots(0) +GivensFGFTParallel<FPP,DEVICE,FPP2>::GivensFGFTParallel(Faust::MatSparse<FPP,DEVICE>& Lap, int J, int t, unsigned int verbosity, const double stoppingError, const bool errIsRel) : GivensFGFT<FPP,DEVICE,FPP2>(Lap, J, verbosity, stoppingError, errIsRel), t(t), fact_nrots(0) { this->facts.resize(round(J/(float)t)); this->always_theta2 = true; diff --git a/wrapper/python/pyfaust/fact.py b/wrapper/python/pyfaust/fact.py index c81bc16ec3b683da20267db6c13e62beffe8265d..1d81184454fb2329849086343113d3f720cd7cf9 100644 --- a/wrapper/python/pyfaust/fact.py +++ b/wrapper/python/pyfaust/fact.py @@ -78,27 +78,27 @@ def svdtj(M, J, t=1): V = W2[:,0:S.shape[0]]*Faust(Id[:,I]) return U,S,V -def eigtj(M, J, t=1, verbosity=0): +def eigtj(M, maxiter, tol=0, relerr=True, nGivens_per_fac=None, verbosity=0): """ - Computes the eigenvalues and the eigenvectors transform (as a Faust object) using the truncated Jacobi algorithm. + Runs the truncated Jacobi algorithm to compute the eigenvalues of M (returned in W) and the corresponding eigenvectors (in Faust V) using the truncated Jacobi algorithm. + + The output is such that V*W.todense()*V.T approximates M. - The eigenvalues and the eigenvectors are approximate. The trade-off between accuracy and sparsity can be set through the - parameters J and t. + parameters maxiter and nGivens_per_fac. Args: M: (numpy.ndarray) the matrix to diagonalize. Must be real and symmetric. - J: (int) defines the number of factors in the eigenvector transform V. - The number of factors is round(J/t). Note that the last permutation factor - is not in count here (in fact, the total number of factors in V is rather - round(J/t)+1). - t: (int) the number of Givens rotations per factor. Note that t is - forced to the value min(J,t). Besides, a value of t such that t > - M.shape[0]/2 won't lead to the desired effect because the maximum - number of rotation matrices per factor is anyway M.shape[0]/2. - The parameter t is meaningful in the parallel version of the - truncated Jacobi algorithm (cf. references below). If t <= 1 (by default) - then the function runs the non-parallel algorithm. + maxiter: (int) defines the number of Givens rotations that are computed in + eigenvector transform V. The number of rotations per factor of V is + defined by nGivens_per_fac. + tol: (float) the tolerance error under what the algorithm stops. By default, + it's zero for not stopping on error criterion. + relErr: (bool) the type of error stopping criterion. Default to True to use + relative error, otherwise (False) the absolute error is used. + nGivens_per_fac: (int) the number of Givens rotations per factor of V, must be + an integer between 1 to M.shape[0]/2 which is the default value (when + nGivens_per_fac == None). verbosity: (int) the level of verbosity, the greater the value the more info. is displayed. @@ -106,11 +106,11 @@ def eigtj(M, J, t=1, verbosity=0): Returns: The tuple (V,W): - V the Faust object representing the approximate eigenvector - transform. V has its last factor being a permutation matrix, - the goal of this factor is to apply to the columns of V the same order as + transform. 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 W. - - W (scipy.sparse.dia.dia_matrix) the approximate diagonal matrix of the eigenvalues - (in ascendant order along the rows/columns). + - W (scipy.sparse.dia.dia_matrix) the diagonal matrix of the + approximate eigenvalues (in ascendant order along the rows/columns). References: [1] Le Magoarou L., Gribonval R. and Tremblay N., "Approximate fast @@ -129,8 +129,8 @@ def eigtj(M, J, t=1, verbosity=0): demo_path = sep.join((get_data_dirpath(),'Laplacian_256_community.mat')) data_dict = loadmat(demo_path) Lap = data_dict['Lap'].astype(np.float) - Uhat, Dhat = eigtj(Lap,J=Lap.shape[0]*100,t=int(Lap.shape[0]/2)) - # Uhat is the Fourier matrix/eigenvectors approximattion as a Faust + Uhat, Dhat = eigtj(Lap, maxiter=Lap.shape[0]*100) + # Uhat is the Fourier matrix/eigenvectors approximation as a Faust # (200 factors + permutation mat.) # Dhat the eigenvalues diagonal matrix approx. print(Uhat) @@ -139,16 +139,18 @@ def eigtj(M, J, t=1, verbosity=0): See also: fgft_givens, fgft_palm """ - return fgft_givens(M, J, t, verbosity) + return fgft_givens(M, maxiter, tol, relerr, nGivens_per_fac, verbosity) -def fgft_givens(Lap, J, t=1, verbosity=0): +def fgft_givens(Lap, maxiter, tol=0.0, relerr=True, nGivens_per_fac=None, verbosity=0): """ Diagonalizes the graph Laplacian matrix Lap using the Givens FGFT algorithm. Args: Lap: the Laplacian matrix as a numpy array. Must be real and symmetric. - J: see eigtj - t: see eigtj + maxiter: see eigtj + tol: see eigtj + relerr: see eigtj + nGivens_per_fac: see eigtj verbosity: see eigtj Returns: @@ -170,17 +172,21 @@ def fgft_givens(Lap, J, t=1, verbosity=0): """ if((isinstance(Lap, np.ndarray) and (Lap.T != Lap).any()) or Lap.shape[0] != Lap.shape[1]): raise ValueError(" the matrix/array must be square and should be symmetric.") - if(not isinstance(J, int)): raise TypeError("J must be a int") - if(J < 1): raise ValueError("J must be >= 1") - if(not isinstance(t, int)): raise TypeError("t must be a int") - if(t < 0): raise ValueError("t must be >= 0") - t = min(t,J) + if(not isinstance(maxiter, int)): raise TypeError("maxiter must be a int") + if(maxiter < 1): raise ValueError("maxiter must be >= 1") + if(not isinstance(nGivens_per_fac, int)): raise TypeError("nGivens_per_fac must be a int") + nGivens_per_fac = max(nGivens_per_fac, 1) + nGivens_per_fac = min(nGivens_per_fac, maxiter) if(isinstance(Lap, np.ndarray)): - core_obj,D = _FaustCorePy.FaustFact.fact_givens_fgft(Lap, J, t, - verbosity) + core_obj,D = _FaustCorePy.FaustFact.fact_givens_fgft(Lap, maxiter, nGivens_per_fac, + verbosity, tol, + relerr) elif(isinstance(Lap, csr_matrix)): - core_obj,D = _FaustCorePy.FaustFact.fact_givens_fgft_sparse(Lap, J, t, - verbosity) + core_obj,D = _FaustCorePy.FaustFact.fact_givens_fgft_sparse(Lap, maxiter, + nGivens_per_fac, + verbosity, + tol, + relerr) else: raise TypeError("The matrix to diagonalize must be a" " scipy.sparse.csr_matrix or a numpy array.") @@ -429,6 +435,7 @@ def _prepare_hierarchical_fact(M, p, callee_name, ret_lambda, ret_params, "with the first factor constraint defined in p.") return p +# experimental block start def hierarchical_constends(M, p, A, B, ret_lambda=False, ret_params=False): """ Tries to approximate M by \f$ A \prod_j S_j B \f$ using the hierarchical. @@ -510,7 +517,9 @@ def hierarchical_constends(M, p, A, B, ret_lambda=False, ret_params=False): return ret_list else: return F +# experimental block end +# experimental block start def palm4msa_constends(M, p, A, B=None, ret_lambda=False): """ Tries to approximate M by \f$ A \prod_j S_j B\f$ using palm4msa (B being optional). @@ -564,6 +573,7 @@ def palm4msa_constends(M, p, A, B=None, ret_lambda=False): return F, _lambda else: return F +# experimental block end def fgft_palm(U, Lap, p, init_D=None, ret_lambda=False, ret_params=False): """ diff --git a/wrapper/python/src/FaustCoreCy.pxd b/wrapper/python/src/FaustCoreCy.pxd index 64a342eb582465e4c81d8b651039e4f52378bca8..410bc797a932af92b35efb9d71ec279bd2e76449 100644 --- a/wrapper/python/src/FaustCoreCy.pxd +++ b/wrapper/python/src/FaustCoreCy.pxd @@ -184,9 +184,14 @@ cdef extern from "FaustFactGivensFGFT.h": cdef FaustCoreCpp[FPP]* fact_givens_fgft[FPP,FPP2](const FPP* Lap, unsigned int num_rows, unsigned int num_cols, unsigned int J, - unsigned int t, FPP* D, unsigned int verbosity) + unsigned int t, FPP* D, unsigned int verbosity, + const double stoppingError, + const bool errIsRel) cdef FaustCoreCpp[FPP]* fact_givens_fgft_sparse[FPP,FPP2](const FPP* data, int* row_ptr, int* id_col, int nnz, unsigned int num_rows, unsigned int num_cols, unsigned int J, - unsigned int t, FPP* D, unsigned int verbosity) + unsigned int t, FPP* D, + unsigned int verbosity, + const double stoppingError, + const bool errIsRel) diff --git a/wrapper/python/src/FaustFactGivensFGFT.h b/wrapper/python/src/FaustFactGivensFGFT.h index 013c590b832a55716e8e1cdb3ca5d255d1db6ef8..c5a86f8861b7e2e43a6a5653d9cb677994868bdb 100644 --- a/wrapper/python/src/FaustFactGivensFGFT.h +++ b/wrapper/python/src/FaustFactGivensFGFT.h @@ -3,11 +3,11 @@ #include <faust_GivensFGFT.h> template<typename FPP, typename FPP2 = float> -FaustCoreCpp<FPP>* fact_givens_fgft(const FPP* Lap, unsigned int num_rows, unsigned int num_cols, unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity = 0); +FaustCoreCpp<FPP>* fact_givens_fgft(const FPP* Lap, unsigned int num_rows, unsigned int num_cols, unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity = 0, const double stoppingError = 0.0, const bool errIsRel = true); template<typename FPP, typename FPP2 = float> FaustCoreCpp<FPP>* fact_givens_fgft_sparse(const FPP* data, int* row_ptr, int* id_col, int nnz, int nrows, int ncols, - unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity = 0); + unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity = 0, const double stoppingError = 0.0, const bool errIsRel = true); template<typename FPP, typename FPP2 = float> diff --git a/wrapper/python/src/FaustFactGivensFGFT.hpp b/wrapper/python/src/FaustFactGivensFGFT.hpp index 13a2568a7f4b326bdca66ecde1a146c44882ec46..4e04497890846582bf90c16e363de165b8485e21 100644 --- a/wrapper/python/src/FaustFactGivensFGFT.hpp +++ b/wrapper/python/src/FaustFactGivensFGFT.hpp @@ -6,23 +6,23 @@ using namespace Faust; template<typename FPP, typename FPP2> FaustCoreCpp<FPP>* fact_givens_fgft_sparse(FPP* data, int* row_ptr, int* id_col, int nnz, int nrows, int ncols, - unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity) + unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity, const double stoppingError, const bool errIsRel) { Faust::MatSparse<FPP, Cpu> mat_Lap(nnz, nrows, ncols, data, id_col, row_ptr); GivensFGFT<FPP, Cpu, FPP2>* algo; if(t <= 1) { - algo = new GivensFGFT<FPP, Cpu, FPP2>(mat_Lap, (int)J, verbosity); + algo = new GivensFGFT<FPP, Cpu, FPP2>(mat_Lap, (int)J, verbosity, stoppingError, errIsRel); } else { - algo = new GivensFGFTParallel<FPP, Cpu, FPP2>(mat_Lap, (int)J, (int) t, verbosity); + algo = new GivensFGFTParallel<FPP, Cpu, FPP2>(mat_Lap, (int)J, (int) t, verbosity, stoppingError, errIsRel); } return fact_givens_fgft_generic(algo, D); } template<typename FPP, typename FPP2> -FaustCoreCpp<FPP>* fact_givens_fgft(const FPP* Lap, unsigned int num_rows, unsigned int num_cols, unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity) +FaustCoreCpp<FPP>* fact_givens_fgft(const FPP* Lap, unsigned int num_rows, unsigned int num_cols, unsigned int J, unsigned int t /* end of input parameters*/, FPP* D, unsigned int verbosity, const double stoppingError, const bool errIsRel) { //TODO: optimization possible here by avoiding Lap copy in MatDense (by //just using the data in Lap as underlying pointer of MatDense) @@ -31,11 +31,11 @@ FaustCoreCpp<FPP>* fact_givens_fgft(const FPP* Lap, unsigned int num_rows, unsig GivensFGFT<FPP, Cpu, FPP2>* algo; if(t <= 1) { - algo = new GivensFGFT<FPP, Cpu, FPP2>(mat_Lap, (int)J, verbosity); + algo = new GivensFGFT<FPP, Cpu, FPP2>(mat_Lap, (int)J, verbosity, stoppingError, errIsRel); } else { - algo = new GivensFGFTParallel<FPP, Cpu, FPP2>(mat_Lap, (int)J, (int) t, verbosity); + algo = new GivensFGFTParallel<FPP, Cpu, FPP2>(mat_Lap, (int)J, (int) t, verbosity, stoppingError, errIsRel); } return fact_givens_fgft_generic(algo, D); } diff --git a/wrapper/python/src/_FaustCorePy.pyx b/wrapper/python/src/_FaustCorePy.pyx index f0a6e431d86cc3ef3e743946954d505cacdb3126..768f14d5db658c7621d29aeca014d00f90609dab 100644 --- a/wrapper/python/src/_FaustCorePy.pyx +++ b/wrapper/python/src/_FaustCorePy.pyx @@ -1350,7 +1350,8 @@ cdef class FaustFact: return core, np.real(_out_buf[0]) @staticmethod - def fact_givens_fgft_sparse(Lap, J, t, verbosity=0): + def fact_givens_fgft_sparse(Lap, J, t, verbosity=0, stoppingError = 0.0, + errIsRel=True): from scipy.sparse import spdiags cdef double [:] data1d #only for csr mat factor cdef int [:] indices # only for csr mat @@ -1374,14 +1375,18 @@ cdef class FaustFact: Lap.nnz, Lap_num_rows, Lap_num_cols, J, t, - &D_view[0], verbosity) + &D_view[0], + verbosity, + stoppingError, + errIsRel) core._isReal = True D_spdiag = spdiags(D, [0], Lap.shape[0], Lap.shape[0]) return core, D_spdiag @staticmethod - def fact_givens_fgft(Lap, J, t, verbosity=0): + def fact_givens_fgft(Lap, J, t, verbosity=0, stoppingError = 0.0, + errIsRel=True): isReal = Lap.dtype in [ 'float', 'float128', 'float16', 'float32', 'float64', 'double'] @@ -1403,9 +1408,11 @@ cdef class FaustFact: core = FaustCore(core=True) core.core_faust_dbl = FaustCoreCy.fact_givens_fgft[double, double](&Lap_view[0,0], - Lap_num_rows, - Lap_num_cols, J, t, - &D_view[0], verbosity) + Lap_num_rows, + Lap_num_cols, J, t, + &D_view[0], verbosity, + stoppingError, + errIsRel) core._isReal = True from scipy.sparse import spdiags