/* Montre l'usage de l'évaluation déférée pour augmenter la vitesse des calculs sur un vecteur. vector a = vector b * N + vector c * vector d */ #include #include #include "getnow.h" #include #include using namespace std; namespace DEFER{ template class BASEOPER{ protected: const T1 &t1; const T2 &t2; public: //using value_type = sizeof(T1)>sizeof(T2) ? typename T1::value_type : typename T2::value_type; using value_type = typename T1::value_type; BASEOPER(const T1 &_t1, const T2 &_t2) :t1(_t1),t2(_t2){ if (t1.size() != t2.size()){ fprintf (stderr,"taille invalide pour les 2 vecteurs: %zu != %zu\n",t1.size(),t2.size()); } } size_t size() const { return t1.size(); } }; template class OPERMULT: public BASEOPER{ public: OPERMULT(const T1 &_t1, const T2 &_t2): BASEOPER(_t1,_t2){} typename BASEOPER::value_type operator [] (int n) const { return this->t1[n] * this->t2[n]; } operator vector::value_type> () const{ vector::value_type> t1; for (size_t i=0; isize(); i++) t1.push_back((*this)[i]); return t1; } }; template auto operator * (const T1 &t1, const T2 &t2) { return OPERMULT(t1,t2); } template class OPERPLUS: public BASEOPER{ public: OPERPLUS(const T1 &_t1, const T2 &_t2): BASEOPER(_t1,_t2){} double operator [] (int n) const { return this->t1[n] + this->t2[n]; } operator vector () const{ vector t1; for (size_t i=0; isize(); i++) t1.push_back((*this)[i]); return t1; } }; template auto operator + (const T1 &t1, const T2 &t2) { return OPERPLUS(t1,t2); } } namespace DEFER2{ template class BASEOPER{ public: using value_type = typename T1::value_type; protected: const T1 &t1; const T2 &t2; public: BASEOPER(const T1 &_t1, const T2 &_t2) :t1(_t1),t2(_t2){ if (t1.size() != t2.size()){ fprintf (stderr,"taille invalide pour les 2 vecteurs: %zu != %zu\n",t1.size(),t2.size()); } } size_t size() const { return t1.size(); } value_type operator [] (int n) const { return static_cast(this)->func(t1[n],t2[n]); } operator vector () const{ vector t1; for (size_t i=0; i class OPERMULT: public BASEOPER>{ public: using value_type = typename BASEOPER>::value_type; value_type func(value_type p1, value_type p2) const{ return p1*p2; } OPERMULT(const T1 &_t1, const T2 &_t2): BASEOPER>(_t1,_t2){} }; template auto operator * (const T1 &t1, const T2 &t2) { return OPERMULT(t1,t2); } template class OPERPLUS: public BASEOPER>{ public: using value_type = typename BASEOPER>::value_type; value_type func(value_type p1, value_type p2) const{ return p1+p2; } OPERPLUS(const T1 &_t1, const T2 &_t2): BASEOPER>(_t1,_t2){} }; template auto operator + (const T1 &t1, const T2 &t2) { return OPERPLUS(t1,t2); } } namespace NONDEFER{ auto operator *(const vector &t1, const vector &t2) { vector ret; for (size_t i=0; i &t1, const vector &t2) { vector ret; for (size_t i=0; i &a, vector &b, bool print) { using namespace DEFER; auto start = getnow(); auto r = (a+b)*(a+b); double somme = 0; for (size_t i=0; i &a, vector &b, bool print) { using namespace DEFER2; auto start = getnow(); auto r = (a+b)*(a+b); double somme = 0; for (size_t i=0; i &a, vector &b, bool print) { using namespace NONDEFER; auto start = getnow(); vector r = (a+b)*(a+b); showtime ("nondefer",start,getnow()); double somme = 0; for (size_t i=0; i a; for (int i=1; i<=nb; i++) a.push_back(i); vector b = a; for (int i=0; i<1; i++){ test_defer(a,b,nb < 10); test_defer2(a,b,nb < 10); test_nondefer(a,b,nb < 10); } if (0){ using namespace DEFER; vector r = a * b; for (auto n:r) printf ("%lf\n",n); r = a + b; for (auto n:r) printf ("%lf\n",n); r = (a + b)*(a+b); for (auto n:r) printf ("%lf\n",n); } if (0){ using namespace NONDEFER; vector r = a * b; for (auto n:r) printf ("%lf\n",n); r = a + b; for (auto n:r) printf ("%lf\n",n); r = (a + b)*(a+b); for (auto n:r) printf ("%lf\n",n); } return 0; }