Mentions légales du service

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

Implement generator mechanism for Faust::TransformHelperPoly and add it in the pyfaust wrapper.

- Set to private Faust::TransformHelperPoly attributes.
- Use RefManager to share between TransformHelperPoly instances generated from the same parent instance the L, rR and other common attributes without copying.
parent 48adedd9
Branches
Tags
No related merge requests found
...@@ -3,6 +3,12 @@ ...@@ -3,6 +3,12 @@
#include "faust_TransformHelper.h" #include "faust_TransformHelper.h"
namespace Faust namespace Faust
{ {
template<typename FPP>
TransformHelper<FPP, Cpu>* basisChebyshev(MatSparse<FPP,Cpu>* L, int32_t K);
template<typename FPP>
void poly(int d, int K, int n, const FPP* basisX, const FPP* coeffs, FPP* out);
/** /**
* \brief This class aims to represent a Chebyshev polynomial basis as a "Faust". * \brief This class aims to represent a Chebyshev polynomial basis as a "Faust".
* *
...@@ -12,9 +18,11 @@ namespace Faust ...@@ -12,9 +18,11 @@ namespace Faust
class TransformHelperPoly : public TransformHelper<FPP,Cpu> class TransformHelperPoly : public TransformHelper<FPP,Cpu>
{ {
static RefManager ref_man;
MatSparse<FPP, Cpu> *L;
MatSparse<FPP, Cpu> *twoL;
MatSparse<FPP, Cpu> *rR;
public: public:
MatSparse<FPP, Cpu> L; //TODO: must be private (and basisChebyshev a friend of this class)
MatSparse<FPP, Cpu> twoL; //TODO: must be private
TransformHelperPoly(const std::vector<MatGeneric<FPP,Cpu> *>& facts, TransformHelperPoly(const std::vector<MatGeneric<FPP,Cpu> *>& facts,
const FPP lambda_, const bool optimizedCopy, const bool cloning_fact, const FPP lambda_, const bool optimizedCopy, const bool cloning_fact,
const bool internal_call) : TransformHelper<FPP,Cpu>(facts, lambda_, optimizedCopy, cloning_fact, internal_call) {} const bool internal_call) : TransformHelper<FPP,Cpu>(facts, lambda_, optimizedCopy, cloning_fact, internal_call) {}
...@@ -23,17 +31,16 @@ namespace Faust ...@@ -23,17 +31,16 @@ namespace Faust
Vect<FPP,Cpu> multiply(const FPP* x, const bool transpose=false, const bool conjugate=false); Vect<FPP,Cpu> multiply(const FPP* x, const bool transpose=false, const bool conjugate=false);
void multiply(const FPP* x, FPP* y, const bool transpose=false, const bool conjugate=false); void multiply(const FPP* x, FPP* y, const bool transpose=false, const bool conjugate=false);
MatDense<FPP, Cpu> multiply(const MatDense<FPP,Cpu> &X, const bool transpose=false, const bool conjugate=false); MatDense<FPP, Cpu> multiply(const MatDense<FPP,Cpu> &X, const bool transpose=false, const bool conjugate=false);
TransformHelper<FPP, Cpu>* next(int K);
TransformHelper<FPP, Cpu>* next();
Vect<FPP, Cpu> poly(MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs); Vect<FPP, Cpu> poly(MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs);
MatDense<FPP, Cpu> poly(int n, MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs); MatDense<FPP, Cpu> poly(int n, MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs);
void poly(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out); void poly(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out);
TransformHelper<FPP, Cpu>* polyFaust(const FPP* coeffs); TransformHelper<FPP, Cpu>* polyFaust(const FPP* coeffs);
~TransformHelperPoly();
friend TransformHelper<FPP,Cpu>* basisChebyshev<>(MatSparse<FPP,Cpu>* L, int32_t K);
}; };
template<typename FPP>
TransformHelper<FPP, Cpu>* basisChebyshev(MatSparse<FPP,Cpu>* L, int32_t K);
template<typename FPP>
void poly(int d, int K, int n, const FPP* basisX, const FPP* coeffs, FPP* out);
} }
#include "faust_TransformHelperPoly.hpp" #include "faust_TransformHelperPoly.hpp"
......
...@@ -5,111 +5,111 @@ ...@@ -5,111 +5,111 @@
namespace Faust namespace Faust
{ {
template<typename FPP> template<typename FPP>
Vect<FPP,Cpu> TransformHelperPoly<FPP>::multiply(const Vect<FPP,Cpu> &x, const bool transpose/*=false*/, const bool conjugate/*=false*/) Vect<FPP,Cpu> TransformHelperPoly<FPP>::multiply(const Vect<FPP,Cpu> &x, const bool transpose/*=false*/, const bool conjugate/*=false*/)
{ {
return std::move(this->multiply(x.getData(), transpose, conjugate)); return std::move(this->multiply(x.getData(), transpose, conjugate));
} }
template<typename FPP> template<typename FPP>
Vect<FPP,Cpu> TransformHelperPoly<FPP>::multiply(const FPP* x, const bool transpose/*=false*/, const bool conjugate/*=false*/) Vect<FPP,Cpu> TransformHelperPoly<FPP>::multiply(const FPP* x, const bool transpose/*=false*/, const bool conjugate/*=false*/)
{ {
int d = L.getNbRow(); int d = L->getNbRow();
int K = this->size(); int K = this->size();
Vect<FPP, Cpu> v0(d*(K+1)); Vect<FPP, Cpu> v0(d*(K+1));
multiply(x, v0.getData(), transpose, conjugate); multiply(x, v0.getData(), transpose, conjugate);
return std::move(v0); return std::move(v0);
} }
template<typename FPP> template<typename FPP>
void TransformHelperPoly<FPP>::multiply(const FPP* x, FPP* y, const bool transpose/*=false*/, const bool conjugate/*=false*/) void TransformHelperPoly<FPP>::multiply(const FPP* x, FPP* y, const bool transpose/*=false*/, const bool conjugate/*=false*/)
{
// std::cout << "TransformHelperPoly<FPP>::multiply(Vect)" << std::endl;
/**
* Recurrence relation (k=1 to K):
* v_{0,k} := [v_{0,k-1} ; v_{1, k-1} ] // concatenation
* v_{1,k} := v_{2,k-1}
* v_{2,k} := 2Lv_{2,k-1} - v_{1,k-1}
*
* First terms:
* v_{0,1} = []
* v_{1,1} = x
* v_{2,1} = Lx
*
* Fx = [v_{0, K} ; v_{1, K} ; v_{2, K}]
*/
int d = L.getNbRow();
Vect<FPP,Cpu> v2, tmp;
int K = this->size();
// seeing how basisChebyshev method is instantiating this class
// K can't be strictly lower than two
v2 = L*Vect<FPP,Cpu>(d, x);//L*x
memcpy(y, x, sizeof(FPP)*d);
memcpy(y+d, v2.getData(), sizeof(FPP)*d);
for(int i=3;i<=K+1;i++)
{ {
int offset = d*(i-3); // std::cout << "TransformHelperPoly<FPP>::multiply(Vect)" << std::endl;
// gemv(L, v2, tmp, FPP(1), FPP(-1)); /**
// v2 = twoL*v2; * Recurrence relation (k=1 to K):
v2.multiplyLeft(twoL); * v_{0,k} := [v_{0,k-1} ; v_{1, k-1} ] // concatenation
v2 -= y+offset; * v_{1,k} := v_{2,k-1}
memcpy(y+d*(i-1), v2.getData(), sizeof(FPP)*d); * v_{2,k} := 2Lv_{2,k-1} - v_{1,k-1}
*
* First terms:
* v_{0,1} = []
* v_{1,1} = x
* v_{2,1} = Lx
*
* Fx = [v_{0, K} ; v_{1, K} ; v_{2, K}]
*/
int d = L->getNbRow();
Vect<FPP,Cpu> v2, tmp;
int K = this->size();
// seeing how basisChebyshev method is instantiating this class
// K can't be strictly lower than two
v2 = *L*Vect<FPP,Cpu>(d, x);//L*x
memcpy(y, x, sizeof(FPP)*d);
memcpy(y+d, v2.getData(), sizeof(FPP)*d);
for(int i=3;i<=K+1;i++)
{
int offset = d*(i-3);
// gemv(L, v2, tmp, FPP(1), FPP(-1));
// v2 = twoL*v2;
v2.multiplyLeft(*twoL);
v2 -= y+offset;
memcpy(y+d*(i-1), v2.getData(), sizeof(FPP)*d);
}
} }
}
// Slower method but kept commented here until further tests // Slower method but kept commented here until further tests
// template<typename FPP> // template<typename FPP>
// MatDense<FPP, Cpu> TransformHelperPoly<FPP>::multiply(MatDense<FPP,Cpu> X, const bool transpose/*=false*/, const bool conjugate/*=false*/) // MatDense<FPP, Cpu> TransformHelperPoly<FPP>::multiply(MatDense<FPP,Cpu> X, const bool transpose/*=false*/, const bool conjugate/*=false*/)
// { // {
//// std::cout << "TransformHelperPoly<FPP>::multiply(MatDense)" << std::endl; //// std::cout << "TransformHelperPoly<FPP>::multiply(MatDense)" << std::endl;
// int d = L.getNbRow(); // int d = L.getNbRow();
// int n = X.getNbCol(); // int n = X.getNbCol();
// int K = this->size(); // int K = this->size();
// MatDense<FPP, Cpu> V0(d*(K+1), n); // MatDense<FPP, Cpu> V0(d*(K+1), n);
// MatDense<FPP,Cpu> V1(d, n), V2 = X, tmp; // MatDense<FPP,Cpu> V1(d, n), V2 = X, tmp;
// memcpy(V1.getData(), X.getData(), sizeof(FPP)*d*n); // memcpy(V1.getData(), X.getData(), sizeof(FPP)*d*n);
// L.multiply(V2, 'N'); // L.multiply(V2, 'N');
// for(int i=2;i<=K;i++) // for(int i=2;i<=K;i++)
// { // {
// memcpy(V0.getData()+d*n*(i-2), V1.getData(), sizeof(FPP)*d*n); // memcpy(V0.getData()+d*n*(i-2), V1.getData(), sizeof(FPP)*d*n);
// tmp = V1; // tmp = V1;
// V1 = V2; // V1 = V2;
// twoL.multiply(V2, 'N'); // twoL.multiply(V2, 'N');
// V2 -= tmp; // V2 -= tmp;
//// gemm(twoL, V2, tmp, (FPP)1.0, (FPP)-1.0, 'N', 'N'); //// gemm(twoL, V2, tmp, (FPP)1.0, (FPP)-1.0, 'N', 'N');
//// V2 = tmp; //// V2 = tmp;
// } // }
// memcpy(V0.getData()+d*n*(K-1), V1.getData(), sizeof(FPP)*d*n); // memcpy(V0.getData()+d*n*(K-1), V1.getData(), sizeof(FPP)*d*n);
// memcpy(V0.getData()+d*n*K, V2.getData(), sizeof(FPP)*d*n); // memcpy(V0.getData()+d*n*K, V2.getData(), sizeof(FPP)*d*n);
// // put bocks in proper order // // put bocks in proper order
// MatDense<FPP,Cpu> V0_ord(d*(K+1), n); // MatDense<FPP,Cpu> V0_ord(d*(K+1), n);
// #pragma omp parallel for // #pragma omp parallel for
// for(int i=0;i<(K+1);i++) // for(int i=0;i<(K+1);i++)
// { // {
// auto i_offset = i*n*d; // auto i_offset = i*n*d;
// for(int j=0;j<n;j++) // for(int j=0;j<n;j++)
// memcpy(V0_ord.getData()+(K+1)*d*j+d*i, V0.getData()+j*d+i_offset, sizeof(FPP)*d); // memcpy(V0_ord.getData()+(K+1)*d*j+d*i, V0.getData()+j*d+i_offset, sizeof(FPP)*d);
// } // }
// return V0_ord; // return V0_ord;
// } // }
template<typename FPP> template<typename FPP>
MatDense<FPP, Cpu> TransformHelperPoly<FPP>::multiply(const MatDense<FPP,Cpu> &X, const bool transpose/*=false*/, const bool conjugate/*=false*/) MatDense<FPP, Cpu> TransformHelperPoly<FPP>::multiply(const MatDense<FPP,Cpu> &X, const bool transpose/*=false*/, const bool conjugate/*=false*/)
{
// std::cout << "TransformHelperPoly<FPP>::multiply(MatDense)" << std::endl;
int d = L->getNbRow();
int K = this->size();
int n = X.getNbCol();
MatDense<FPP,Cpu> V0_ord(d*(K+1), n);
auto scale = (K+1)*d;
#pragma omp parallel for
for(int i=0;i<n;i++)
{ {
// std::cout << "TransformHelperPoly<FPP>::multiply(MatDense)" << std::endl; Vect<FPP,Cpu> x(d, X.getData()+i*d);
int d = L.getNbRow(); auto y = multiply(x);
int K = this->size(); memcpy(V0_ord.getData()+scale*i, y.getData(), sizeof(FPP)*scale);
int n = X.getNbCol();
MatDense<FPP,Cpu> V0_ord(d*(K+1), n);
auto scale = (K+1)*d;
#pragma omp parallel for
for(int i=0;i<n;i++)
{
Vect<FPP,Cpu> x(d, X.getData()+i*d);
auto y = multiply(x);
memcpy(V0_ord.getData()+scale*i, y.getData(), sizeof(FPP)*scale);
}
return V0_ord;
} }
return V0_ord;
}
template<typename FPP> template<typename FPP>
Vect<FPP, Cpu> TransformHelperPoly<FPP>::poly(MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs) Vect<FPP, Cpu> TransformHelperPoly<FPP>::poly(MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs)
...@@ -121,7 +121,7 @@ namespace Faust ...@@ -121,7 +121,7 @@ namespace Faust
template<typename FPP> template<typename FPP>
MatDense<FPP, Cpu> TransformHelperPoly<FPP>::poly(int n, MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs) MatDense<FPP, Cpu> TransformHelperPoly<FPP>::poly(int n, MatDense<FPP,Cpu> & basisX, Vect<FPP, Cpu> coeffs)
{ {
int d = L.getNbRow(); int d = L->getNbRow();
MatDense<FPP,Cpu> Y(d, n); MatDense<FPP,Cpu> Y(d, n);
this->poly(d, n, basisX.getData(), coeffs.getData(), Y.getData()); this->poly(d, n, basisX.getData(), coeffs.getData(), Y.getData());
return Y; return Y;
...@@ -134,15 +134,58 @@ namespace Faust ...@@ -134,15 +134,58 @@ namespace Faust
Faust::poly(d, K, n, basisX, coeffs, out); Faust::poly(d, K, n, basisX, coeffs, out);
} }
template<typename FPP>
TransformHelper<FPP, Cpu>* TransformHelperPoly<FPP>::next()
{
int K = this->size();
return next(K+1);
}
template<typename FPP>
TransformHelper<FPP, Cpu>* TransformHelperPoly<FPP>::next(int K)
{
auto old_K = this->size();
auto d = L->getNbRow();
MatSparse<FPP,Cpu> Id, zero, R;
std::vector<MatGeneric<FPP,Cpu>*> facts(K);
facts.resize(K);
for(int i=0;i<old_K;i++)
facts[K-i-1] = this->get_gen_fact_nonconst(old_K-1-i);
#pragma omp parallel for private(Id, zero, R)
for(int i=old_K+1;i <= K; i++)
{
//TODO: refactor with basisChebyshev
Id.resize(i*d, i*d, i*d);
Id.setEyes();
zero.resize(0, d, (i-2)*d);
R.hstack(zero, *rR);
auto Ti = new MatSparse<FPP,Cpu>();
Ti->vstack(Id, R);
facts[K-i] = Ti;
}
auto basisP = new TransformHelperPoly<FPP>(facts, (FPP)1.0,
/* optimizedCopy */ false,
/* cloning_fact */ false,
/* internal_call */ true);
//TODO: use reference manager to avoid copies
basisP->L = L;
ref_man.acquire(L);
basisP->twoL = twoL;
ref_man.acquire(twoL);
basisP->rR = rR;
ref_man.acquire(rR);
return basisP;
}
template<typename FPP> template<typename FPP>
TransformHelper<FPP, Cpu>* TransformHelperPoly<FPP>::polyFaust(const FPP* coeffs) TransformHelper<FPP, Cpu>* TransformHelperPoly<FPP>::polyFaust(const FPP* coeffs)
{ {
// Id = sp.eye(L.shape[1], format="csr") // Id = sp.eye(L.shape[1], format="csr")
// scoeffs = sp.hstack(tuple(Id*coeffs[i] for i in range(0, K+1)), // scoeffs = sp.hstack(tuple(Id*coeffs[i] for i in range(0, K+1)),
// format="csr") // format="csr")
MatSparse<FPP,Cpu> Id, Id1; MatSparse<FPP,Cpu> Id, Id1;
MatSparse<FPP,Cpu> coeffDiags; MatSparse<FPP,Cpu> coeffDiags;
auto d = L.getNbRow(); auto d = L->getNbRow();
int K = this->size(); int K = this->size();
Id.resize(d, d, d); Id.resize(d, d, d);
Id.setEyes(); Id.setEyes();
...@@ -170,13 +213,33 @@ namespace Faust ...@@ -170,13 +213,33 @@ namespace Faust
/* internal_call */ true); /* internal_call */ true);
} }
template<typename FPP>
Faust::RefManager Faust::TransformHelperPoly<FPP>::ref_man([](void *fact)
{
#ifdef DEBUG
std::cout << "Faust::TransformHelperPoly delete" << std::endl;
#endif
delete static_cast<MatGeneric<FPP,Cpu>*>(fact);
});
template<typename FPP>
TransformHelperPoly<FPP>::~TransformHelperPoly()
{
#ifdef FAUST_VERBOSE
std::cout << "~TransformHelperPoly()" << std::endl;
#endif
ref_man.release(L);
ref_man.release(twoL);
ref_man.release(rR);
}
template<typename FPP> template<typename FPP>
TransformHelper<FPP,Cpu>* basisChebyshev(MatSparse<FPP,Cpu>* L, int32_t K) TransformHelper<FPP,Cpu>* basisChebyshev(MatSparse<FPP,Cpu>* L, int32_t K)
{ {
// assuming L is symmetric // assuming L is symmetric
MatSparse<FPP,Cpu> *T1, *T2; MatSparse<FPP,Cpu> *T1, *T2;
auto d = L->getNbRow(); auto d = L->getNbRow();
MatSparse<FPP,Cpu> Id, twoL, minus_Id, rR, R, zero; MatSparse<FPP,Cpu> Id, twoL, minus_Id, *rR, R, zero;
std::vector<MatGeneric<FPP,Cpu>*> facts(K); std::vector<MatGeneric<FPP,Cpu>*> facts(K);
if(K == 0) if(K == 0)
return TransformHelper<FPP,Cpu>::eyeFaust(d,d); return TransformHelper<FPP,Cpu>::eyeFaust(d,d);
...@@ -201,21 +264,22 @@ namespace Faust ...@@ -201,21 +264,22 @@ namespace Faust
minus_Id.resize(d,d,d); minus_Id.resize(d,d,d);
minus_Id.setEyes(); minus_Id.setEyes();
minus_Id *= FPP(-1); minus_Id *= FPP(-1);
rR.hstack(minus_Id, twoL); rR = new MatSparse<FPP,Cpu>();
rR->hstack(minus_Id, twoL);
// T2 // T2
Id.resize(2*d, 2*d, 2*d); Id.resize(2*d, 2*d, 2*d);
Id.setEyes(); Id.setEyes();
T2 = new MatSparse<FPP,Cpu>(); T2 = new MatSparse<FPP,Cpu>();
T2->vstack(Id, rR); T2->vstack(Id, *rR);
facts[K-2] = T2; facts[K-2] = T2;
// T3 to TK // T3 to TK
#pragma omp parallel for private(Id, zero, R) #pragma omp parallel for private(Id, zero, R)
for(int i=3;i<K+1;i++) for(int i=3;i<K+1;i++)
{ {
Id.resize(i*d, i*d, i*d); Id.resize(i*d, i*d, i*d);
Id.setEyes(); Id.setEyes();
zero.resize(0, d, (i-2)*d); zero.resize(0, d, (i-2)*d);
R.hstack(zero, rR); R.hstack(zero, *rR);
auto Ti = new MatSparse<FPP,Cpu>(); auto Ti = new MatSparse<FPP,Cpu>();
Ti->vstack(Id, R); Ti->vstack(Id, R);
facts[K-i] = Ti; facts[K-i] = Ti;
...@@ -224,9 +288,13 @@ namespace Faust ...@@ -224,9 +288,13 @@ namespace Faust
/* optimizedCopy */ false, /* optimizedCopy */ false,
/* cloning_fact */ false, /* cloning_fact */ false,
/* internal_call */ true); /* internal_call */ true);
basisP->L = *L; basisP->L = new MatSparse<FPP,Cpu>(*L);
basisP->twoL = *L; Faust::TransformHelperPoly<FPP>::ref_man.acquire(basisP->L);
basisP->twoL *= 2; basisP->twoL = new MatSparse<FPP,Cpu>(*L);
*(basisP->twoL) *= 2;
Faust::TransformHelperPoly<FPP>::ref_man.acquire(basisP->twoL);
basisP->rR = rR;
Faust::TransformHelperPoly<FPP>::ref_man.acquire(rR);
return basisP; return basisP;
} }
...@@ -235,7 +303,7 @@ namespace Faust ...@@ -235,7 +303,7 @@ namespace Faust
{ {
auto K_plus_1 = K+1; auto K_plus_1 = K+1;
auto d_K_plus_1 = d*K_plus_1; auto d_K_plus_1 = d*K_plus_1;
// #pragma omp parallel for // most likely counterproductive to use OpenMP here, Eigen is already multithreading scalar product in the loop // #pragma omp parallel for // most likely counterproductive to use OpenMP here, Eigen is already multithreading scalar product in the loop
for(int i=0;i<n;i++) for(int i=0;i<n;i++)
{ {
Eigen::Map<Eigen::Matrix<FPP, Eigen::Dynamic, Eigen::Dynamic>> mat_basisX(const_cast<FPP*>(basisX+d_K_plus_1*i), d, K_plus_1); //constcast is not dangerous, no modification is done later Eigen::Map<Eigen::Matrix<FPP, Eigen::Dynamic, Eigen::Dynamic>> mat_basisX(const_cast<FPP*>(basisX+d_K_plus_1*i), d, K_plus_1); //constcast is not dangerous, no modification is done later
......
...@@ -75,7 +75,11 @@ def basis(L, K, basis_name, ret_gen=False, dev='cpu', T0=None, impl="native"): ...@@ -75,7 +75,11 @@ def basis(L, K, basis_name, ret_gen=False, dev='cpu', T0=None, impl="native"):
if basis_name.lower() == 'chebyshev': if basis_name.lower() == 'chebyshev':
if impl == "native": if impl == "native":
F = FaustPoly(core_obj=_FaustCorePy.FaustCore.polyBasis(L, K)) F = FaustPoly(core_obj=_FaustCorePy.FaustCore.polyBasis(L, K))
return F if ret_gen:
g = F._generator()
return F, g
else:
return F
elif impl == "py": elif impl == "py":
return Chebyshev(L, K, ret_gen=ret_gen, dev=dev, T0=T0) return Chebyshev(L, K, ret_gen=ret_gen, dev=dev, T0=T0)
else: else:
...@@ -294,4 +298,11 @@ class FaustPoly(Faust): ...@@ -294,4 +298,11 @@ class FaustPoly(Faust):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(FaustPoly, self).__init__(*args, **kwargs) super(FaustPoly, self).__init__(*args, **kwargs)
def _generator(self):
F = self
while True:
F_next = FaustPoly(core_obj=F.m_faust.polyNext())
F = F_next
yield F
# experimental block end # experimental block end
...@@ -122,6 +122,7 @@ class FaustCoreCpp ...@@ -122,6 +122,7 @@ class FaustCoreCpp
FaustCoreCpp<FPP,DEV>* clone() const; FaustCoreCpp<FPP,DEV>* clone() const;
void polyCoeffs(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out) const; void polyCoeffs(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out) const;
FaustCoreCpp<FPP,DEV>* polyCoeffs(const FPP* coeffs); FaustCoreCpp<FPP,DEV>* polyCoeffs(const FPP* coeffs);
FaustCoreCpp<FPP,DEV>* polyNext() const;
void device(char* dev) const; void device(char* dev) const;
~FaustCoreCpp(); ~FaustCoreCpp();
static FaustCoreCpp<FPP,DEV>* randFaust(unsigned int t, static FaustCoreCpp<FPP,DEV>* randFaust(unsigned int t,
......
...@@ -191,6 +191,16 @@ void FaustCoreCpp<FPP,DEV>::multiply(FPP* value_y,int nbrow_y,int nbcol_y, const ...@@ -191,6 +191,16 @@ void FaustCoreCpp<FPP,DEV>::multiply(FPP* value_y,int nbrow_y,int nbcol_y, const
memcpy(value_y,Y.getData(),sizeof(FPP)*nbrow_y*nbcol_y); memcpy(value_y,Y.getData(),sizeof(FPP)*nbrow_y*nbcol_y);
} }
} }
template<typename FPP, FDevice DEV>
FaustCoreCpp<FPP,DEV>* FaustCoreCpp<FPP,DEV>::polyNext() const
{
Faust::TransformHelperPoly<FPP> *transform_poly = dynamic_cast<Faust::TransformHelperPoly<FPP>*>(this->transform);
if(nullptr)
throw std::runtime_error("polyCoeffs can only be used on a Poly. specialized Faust.");
auto th = transform_poly->next();
FaustCoreCpp<FPP,DEV>* core = new FaustCoreCpp<FPP,DEV>(th);
return core;
}
template<typename FPP, FDevice DEV> template<typename FPP, FDevice DEV>
void FaustCoreCpp<FPP,DEV>::polyCoeffs(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out) const void FaustCoreCpp<FPP,DEV>::polyCoeffs(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out) const
......
...@@ -115,6 +115,7 @@ cdef extern from "FaustCoreCpp.h": ...@@ -115,6 +115,7 @@ cdef extern from "FaustCoreCpp.h":
FaustCoreCpp[FPP]* clone() FaustCoreCpp[FPP]* clone()
void polyCoeffs(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out) const void polyCoeffs(int d, int n, const FPP* basisX, const FPP* coeffs, FPP* out) const
FaustCoreCpp[FPP]* polyCoeffs(const FPP* coeffs) const FaustCoreCpp[FPP]* polyCoeffs(const FPP* coeffs) const
FaustCoreCpp[FPP]* polyNext() const
@staticmethod @staticmethod
FaustCoreCpp[FPP]* randFaust(int faust_nrows, int faust_ncols, FaustCoreCpp[FPP]* randFaust(int faust_nrows, int faust_ncols,
unsigned int t, unsigned int t,
......
...@@ -575,6 +575,14 @@ cdef class FaustCore: ...@@ -575,6 +575,14 @@ cdef class FaustCore:
core.core_faust_cplx = self.core_faust_cplx.polyCoeffs(&cview_cplx[0]) core.core_faust_cplx = self.core_faust_cplx.polyCoeffs(&cview_cplx[0])
return core return core
def polyNext(self):
core = FaustCore(core=True)
core._isReal = self._isReal
if(self._isReal):
core.core_faust_dbl = self.core_faust_dbl.polyNext()
else:
core.core_faust_cplx = self.core_faust_cplx.polyNext()
return core
# Left-Multiplication by a Faust F # Left-Multiplication by a Faust F
# y=multiply(F,M) is equivalent to y=F*M # y=multiply(F,M) is equivalent to y=F*M
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment