Mentions légales du service

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

Add a variadic template ctor for TransformHelper, add push_back_() related functions and a test.

It eases the creation of TransformHelper objects by passing any arguments of type Transform, TransformHelper or std::vector<MatGeneric*> which are used to form a sequence of factors in the new TransformHelper object (in the same order and without any copy).

Modify Transform::push_back() to allow not copying a MatGeneric.

Example: see misc/test/src/C++/unit/test_TransformHelper_variadic_template_ctor.cpp.in

Other minor changes.
parent c6d84531
No related branches found
No related tags found
No related merge requests found
...@@ -156,7 +156,7 @@ endif() ...@@ -156,7 +156,7 @@ endif()
if(NOT NOCPPTESTS) if(NOT NOCPPTESTS)
foreach(TEST_FPP float double) foreach(TEST_FPP float double)
foreach(FILE faust_mult faust_mult_cplx test_Vect_min test_MatDense_get_row test_MatDense_lower_upper_tri test_MatDense_nonzeros_indices test_Transform_move test_TransformHelper_and_Transform_copy_ctor test_TransformHelper_and_Transform_fac_iterato test_MatDense_min faust_transform_omp_mul faust_pruneout faust_transform_optimize_storage faust_transform_optimize faust_prox_blockdiag) foreach(FILE faust_mult faust_mult_cplx test_Vect_min test_MatDense_get_row test_MatDense_lower_upper_tri test_MatDense_nonzeros_indices test_Transform_move test_TransformHelper_and_Transform_copy_ctor test_TransformHelper_and_Transform_fac_iterato test_TransformHelper_variadic_template_ctor test_MatDense_min faust_transform_omp_mul faust_pruneout faust_transform_optimize_storage faust_transform_optimize faust_prox_blockdiag)
set(TEST_BIN_FILE ${FILE}_${TEST_FPP}) set(TEST_BIN_FILE ${FILE}_${TEST_FPP})
set(TEST_FILE_CPP ${TEST_BIN_FILE}.cpp) set(TEST_FILE_CPP ${TEST_BIN_FILE}.cpp)
message(STATUS ${TEST_FILE_CPP}) message(STATUS ${TEST_FILE_CPP})
......
...@@ -48,8 +48,7 @@ ...@@ -48,8 +48,7 @@
/** unit test for Transform move ctor and = op. overload. /** unit test for Transform begin() end end() factor iterators.
* The goal is to test that factors are not duplicated in memory (like copy ctor and = overload do).
*/ */
typedef @TEST_FPP@ FPP; typedef @TEST_FPP@ FPP;
...@@ -97,7 +96,7 @@ int main(int argc, char* argv[]) ...@@ -97,7 +96,7 @@ int main(int argc, char* argv[])
{ {
MatGeneric<FPP,Cpu>* ref_fact = facts[i]; MatGeneric<FPP,Cpu>* ref_fact = facts[i];
MatGeneric<FPP,Cpu>* test_fact2 = *(t.begin()+i); MatGeneric<FPP,Cpu>* test_fact2 = *(t.begin()+i);
cout << "orig ptr fact[" << i << "]: " << ref_fact << " the copied one by ctor: "<< test_fact2 << "(equality tested)." << endl; cout << "orig ptr fact[" << i << "]: " << (void*)ref_fact << " the copied one by ctor: "<< test_fact2 << "(equality tested)." << endl;
assert(ref_fact == test_fact2); assert(ref_fact == test_fact2);
} }
...@@ -109,7 +108,7 @@ int main(int argc, char* argv[]) ...@@ -109,7 +108,7 @@ int main(int argc, char* argv[])
{ {
unsigned long long ref_fact = th.get_fact_addr(i); unsigned long long ref_fact = th.get_fact_addr(i);
unsigned long long test_fact4 = (unsigned long long)(*(th.begin()+i)); unsigned long long test_fact4 = (unsigned long long)(*(th.begin()+i));
cout << "orig ptr fact[" << i << "]: " << ref_fact << " the copied one by ctor: " << ((void*)test_fact4) << "(equality tested)."<< endl; cout << "orig ptr fact[" << i << "]: " << (void*)ref_fact << " the copied one by ctor: " << ((void*)test_fact4) << "(equality tested)."<< endl;
assert((unsigned long long) ref_fact == test_fact4); assert((unsigned long long) ref_fact == test_fact4);
} }
......
/****************************************************************************/
/* Description: */
/* unitary test for testing multiplication by faust with real scalar */
/* */
/* For more information on the FAuST Project, please visit the website */
/* of the project : <http://faust.inria.fr> */
/* */
/* License: */
/* Copyright (2020): Hakim HADJ-DJILANI */
/* Nicolas Bellot, Adrien Leman, Thomas Gautrais, */
/* Luc Le Magoarou, Remi Gribonval */
/* INRIA Rennes, FRANCE */
/* http://www.inria.fr/ */
/* */
/* The FAuST Toolbox is distributed under the terms of the GNU Affero */
/* General Public License. */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU Affero General Public License as */
/* published by the Free Software Foundation. */
/* */
/* This program is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
/* See the GNU Affero General Public License for more details. */
/* */
/* You should have received a copy of the GNU Affero General Public */
/* License along with this program. */
/* If not, see <http://www.gnu.org/licenses/>. */
/* */
/* Contacts: */
/* Nicolas Bellot : nicolas.bellot@inria.fr */
/* Adrien Leman : adrien.leman@inria.fr */
/* Thomas Gautrais : thomas.gautrais@inria.fr */
/* Luc Le Magoarou : luc.le-magoarou@inria.fr */
/* Remi Gribonval : remi.gribonval@inria.fr */
/* */
/* References: */
/* [1] Le Magoarou L. and Gribonval R., "Flexible multi-layer sparse */
/* approximations of matrices and applications", Journal of Selected */
/* Topics in Signal Processing, 2016. */
/* <https://hal.archives-ouvertes.fr/hal-01167948v1> */
/****************************************************************************/
#include "faust_MatDense.h"
#include "faust_MatSparse.h"
#include "faust_Transform.h"
#include "faust_TransformHelper.h"
#include <string>
/** unit test for TransformHelper variadic template ctor
* The goal is to test that factors are not duplicated in memory and it works when passing anything among a TransformHelper, Transform objects or a vector of MatGeneric<FPP,Cpu*> (anything that supports begin() and end() ops).
*/
typedef @TEST_FPP@ FPP;
using namespace Faust;
int main(int argc, char* argv[])
{
if (typeid(FPP) == typeid(double))
{
cout<<"floating point precision == double"<<endl;
}
if (typeid(FPP) == typeid(float))
{
cout<<"floating point precision == float"<<endl;
}
int mat_nrows = 10;
int mat_ncols = 10;
int n_mats = 5;
int n_sparse_mats = 2;
vector<MatGeneric<FPP,Cpu>*> facts(n_mats);
for(int i=0;i<n_sparse_mats;i++)
{
Faust::MatSparse<FPP,Cpu>* mat = Faust::MatSparse<FPP,Cpu>::randMat(mat_nrows, mat_ncols, .5);
facts[i] = mat;
}
for(int i=n_sparse_mats;i<n_mats;i++)
{
MatDense<FPP,Cpu>* mat = MatDense<FPP,Cpu>::randMat(mat_nrows, mat_ncols);
facts[i] = mat;
}
Faust::Transform<FPP,Cpu> t(facts, 1.0, false, false); //don't clone factors
TransformHelper<FPP,Cpu> th(t);
auto f = {facts[n_mats-1]}; //unfortunately TransformHelper ctor doesn't work directly with facts[n_mats-1]
// we have to create the initalizer_list separately and pass it to the ctor after
auto Mf = facts[n_mats-1];
Faust::TransformHelper<FPP, Cpu> th_(th, t, facts, f);// {facts[n_mats-1]});
th_.display();
cout << "t=" << endl;
t.Display();
int i;
for(i=0;i<th.size();i++)
{
assert(th.get_fact_addr(i) == th_.get_fact_addr(i));
}
// testing adding of t factors in th_
int j;
for(j=i;j<i+t.size();j++)
{
assert((*(t.begin()+j-i)) == facts[j-i]);
cout << "orig ptr fact[" << i << "]: " << (void*)*(t.begin()+j-i) << " the copied one by ctor: " << ((void*)*(th_.begin()+j)) << "(equality tested)."<< endl;
assert((*(t.begin()+j-i)) == *(th_.begin()+j));
}
// testing adding of facts in th_
int k;
for(k=j;k<j+t.size();k++)
{
assert(facts[k-j] == *(th_.begin()+k));
}
// testing f, last added factor in th_ // Faust::TransformHelper<FPP, Cpu> th_(th, t, facts, f);
assert(facts[k-j-1] == *(th_.begin()+k));
}
...@@ -193,8 +193,12 @@ namespace Faust ...@@ -193,8 +193,12 @@ namespace Faust
* \param optimizedCopy (optional) : boolean to control which type of copy of the fact is made, * \param optimizedCopy (optional) : boolean to control which type of copy of the fact is made,
if True, the copy is optimized, the dynamic type of the factor can changed if True, the copy is optimized, the dynamic type of the factor can changed
if False, the dynamic type stay the same if False, the dynamic type stay the same
(default value false)*/ (default value false). This argument is ignored if copying==false.
void push_back(const Faust::MatGeneric<FPP,Cpu>* M, const bool optimizedCopy=false, const bool conjugate=false);
* \param conjugate (optional): to conjugate the factor before pushing (works only if copying==true).
* \param copying (optional): true to duplicate the factor in memory and push the copy. Otherwise the same pointer is pushed.
*/
void push_back(const Faust::MatGeneric<FPP,Cpu>* M, const bool optimizedCopy=false, const bool conjugate=false, const bool copying=true);
......
...@@ -255,6 +255,7 @@ Faust::Transform<FPP,Cpu>::Transform(const std::vector<Faust::MatSparse<FPP,Cpu> ...@@ -255,6 +255,7 @@ Faust::Transform<FPP,Cpu>::Transform(const std::vector<Faust::MatSparse<FPP,Cpu>
if(!dtor_delete_data) ref_man.acquire(data[i]); if(!dtor_delete_data) ref_man.acquire(data[i]);
} }
} }
template<typename FPP> template<typename FPP>
Faust::Transform<FPP,Cpu>::Transform(const Transform<FPP, Cpu>* A, const bool transpose_A, const bool conj_A, const Transform<FPP, Cpu>* B, const bool transpose_B, const bool conj_B): Faust::Transform<FPP,Cpu>::Transform(const Transform<FPP, Cpu>* A, const bool transpose_A, const bool conj_A, const Transform<FPP, Cpu>* B, const bool transpose_B, const bool conj_B):
data(std::vector<Faust::MatGeneric<FPP,Cpu>*>()), totalNonZeros(0), dtor_delete_data(false) data(std::vector<Faust::MatGeneric<FPP,Cpu>*>()), totalNonZeros(0), dtor_delete_data(false)
...@@ -855,7 +856,7 @@ faust_unsigned_int Faust::Transform<FPP,Cpu>::get_fact_nnz(const faust_unsigned_ ...@@ -855,7 +856,7 @@ faust_unsigned_int Faust::Transform<FPP,Cpu>::get_fact_nnz(const faust_unsigned_
} }
template<typename FPP> template<typename FPP>
void Faust::Transform<FPP,Cpu>::push_back(const Faust::MatGeneric<FPP,Cpu>* M,const bool optimizedCopy /*default value = false */, const bool conjugate) void Faust::Transform<FPP,Cpu>::push_back(const Faust::MatGeneric<FPP,Cpu>* M, const bool optimizedCopy /*default value = false */, const bool conjugate /* default value = false*/, const bool copying /* default to true */)
{ {
if (size()>0) if (size()>0)
{ {
...@@ -864,11 +865,20 @@ void Faust::Transform<FPP,Cpu>::push_back(const Faust::MatGeneric<FPP,Cpu>* M,co ...@@ -864,11 +865,20 @@ void Faust::Transform<FPP,Cpu>::push_back(const Faust::MatGeneric<FPP,Cpu>* M,co
handleError(m_className,"push_back : incorrect dimensions"); handleError(m_className,"push_back : incorrect dimensions");
} }
} }
Faust::MatGeneric<FPP,Cpu>* M_copy = M->Clone(optimizedCopy); Faust::MatGeneric<FPP,Cpu>* M_;
if(conjugate) M_copy->conjugate(); if(copying)
data.push_back(M_copy); {
if(!dtor_delete_data) ref_man.acquire(M_copy); M_ = M->Clone(optimizedCopy);
totalNonZeros += M_copy->getNonZeros(); if(conjugate) M_->conjugate();
}
else
{
if(conjugate || optimizedCopy) throw runtime_error("copying argument mustn't be true if any of optimizedCopy or conjugate is true.");
M_ = const_cast<Faust::MatGeneric<FPP,Cpu>*>(M);
}
data.push_back(M_);
if(!dtor_delete_data) ref_man.acquire(M_);
totalNonZeros += M_->getNonZeros();
#ifdef __COMPILE_TIMERS__ #ifdef __COMPILE_TIMERS__
this->t_multiply_vector.push_back(Faust::Timer()); this->t_multiply_vector.push_back(Faust::Timer());
......
...@@ -95,7 +95,7 @@ namespace Faust { ...@@ -95,7 +95,7 @@ namespace Faust {
TransformHelper(TransformHelper<FPP,Cpu>* th, Slice s[2]); TransformHelper(TransformHelper<FPP,Cpu>* th, Slice s[2]);
TransformHelper(TransformHelper<FPP,Cpu>* th, faust_unsigned_int* row_ids, faust_unsigned_int num_rows, faust_unsigned_int* col_ids, faust_unsigned_int num_cols); TransformHelper(TransformHelper<FPP,Cpu>* th, faust_unsigned_int* row_ids, faust_unsigned_int num_rows, faust_unsigned_int* col_ids, faust_unsigned_int num_cols);
TransformHelper(Transform<FPP,Cpu> &t, const bool moving=false); TransformHelper(Transform<FPP,Cpu> &t, const bool moving=false);
template<typename ...GList> TransformHelper(GList& ... t);
Vect<FPP,Cpu> multiply(const Vect<FPP,Cpu> x, const bool transpose=false, const bool conjugate=false); Vect<FPP,Cpu> multiply(const Vect<FPP,Cpu> x, const bool transpose=false, const bool conjugate=false);
// MatDense<FPP,Cpu> multiply(const MatDense<FPP,Cpu> A) const; // MatDense<FPP,Cpu> multiply(const MatDense<FPP,Cpu> A) const;
MatDense<FPP, Cpu> multiply(const MatDense<FPP,Cpu> A, const bool transpose=false, const bool conjugate=false); MatDense<FPP, Cpu> multiply(const MatDense<FPP,Cpu> A, const bool transpose=false, const bool conjugate=false);
...@@ -106,7 +106,12 @@ namespace Faust { ...@@ -106,7 +106,12 @@ namespace Faust {
TransformHelper<FPP, Cpu>* multiply(TransformHelper<FPP, Cpu>*); TransformHelper<FPP, Cpu>* multiply(TransformHelper<FPP, Cpu>*);
TransformHelper<FPP, Cpu>* multiply(FPP& scalar); TransformHelper<FPP, Cpu>* multiply(FPP& scalar);
void push_back(const MatGeneric<FPP,Cpu>* M, bool optimizedCopy=false); template<typename Head, typename ... Tail>
void push_back_(Head& h, Tail&... t);
void push_back_();
void push_back(const MatGeneric<FPP,Cpu>* M, const bool optimizedCopy=false, const bool copying=false);
faust_unsigned_int getNbRow() const; faust_unsigned_int getNbRow() const;
faust_unsigned_int getNbCol() const; faust_unsigned_int getNbCol() const;
faust_unsigned_int getNBytes() const; faust_unsigned_int getNBytes() const;
......
...@@ -182,6 +182,13 @@ namespace Faust { ...@@ -182,6 +182,13 @@ namespace Faust {
this->mul_order_opt_mode = th->mul_order_opt_mode; this->mul_order_opt_mode = th->mul_order_opt_mode;
} }
template<typename FPP>
template<typename ... GList>
TransformHelper<FPP,Cpu>::TransformHelper(GList& ... t) : TransformHelper<FPP,Cpu>()
{
this->push_back_(t...);
}
template<typename FPP> template<typename FPP>
MatDense<FPP,Cpu> TransformHelper<FPP,Cpu>::multiply(const MatSparse<FPP,Cpu> A, const bool transpose /* deft to false */, const bool conjugate) MatDense<FPP,Cpu> TransformHelper<FPP,Cpu>::multiply(const MatSparse<FPP,Cpu> A, const bool transpose /* deft to false */, const bool conjugate)
{ {
...@@ -526,11 +533,32 @@ namespace Faust { ...@@ -526,11 +533,32 @@ namespace Faust {
} }
template<typename FPP> template<typename FPP>
void TransformHelper<FPP,Cpu>::push_back(const MatGeneric<FPP,Cpu>* M, bool optimizedCopy /* false by default */) void TransformHelper<FPP,Cpu>::push_back(const MatGeneric<FPP,Cpu>* M, const bool optimizedCopy /* false by default */, const bool copying /* true to default */)
{
//warning: should not be called after initialization of factors (to respect the immutability property)
//this function is here only for python wrapper (TODO: see how to modify that wrapper in order to delete this function after or just use it internally -- not py/matfaust)
this->transform->push_back(M, optimizedCopy, is_conjugate, copying); //2nd argument is for opt. (possibly converting dense <-> sparse)
}
template<typename FPP>
template<typename Head, typename ... Tail>
void TransformHelper<FPP,Cpu>::push_back_(Head& h, Tail&... t)
{
// for(auto f: h)
// this->push_back(f, false, false);
for(auto it=h.begin(); it < h.end(); it++)
{
auto f = *it;
this->push_back(f, false, false);
}
// this->push_back(h, false, false);
this->push_back_(t...);
}
template<typename FPP>
void TransformHelper<FPP,Cpu>::push_back_()
{ {
//warning: should not be called after initialization of factors (to respect the immutable property) // do nothing, here just for empty tail of above function
//this function is here only for python wrapper (TODO: see how to modify that wrapper in order to delete this function after)
this->transform->push_back(M, optimizedCopy, is_conjugate); //2nd argument is for opt. (possibly converting dense <-> sparse)
} }
template<typename FPP> template<typename FPP>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment