#include #include #include using std::cout; using std::string; using std::ostream; using std::ostringstream; class MyMat; class MyVec; class Vadd; class MVmul; class MVmuladd; struct Vadd { // represents v1+v2 const MyVec *v1, *v2; Vadd(const MyVec &_v1, const MyVec &_v2) { v1 = &_v1; v2 = &_v2; } operator MyVec(); // This computes v1+v2 }; struct MVmul { // represents m*v const MyMat *m; // use references const MyVec *v; // to avoid copying MVmul(const MyMat &_m, const MyVec &_v) { m = &_m; v = &_v; } operator MyVec(); // This computes m*v }; struct MVmuladd { // represents m*v1+v2 const MyMat *m; const MyVec *v1, *v2; MVmuladd(const MVmul &mv, const MyVec &_v2) { m = mv.m; v1 = mv.v; v2 = &_v2; } operator MyVec(); // This computes m*v1+v2 }; class MyMat { string name; public: friend class MyVec; friend MyVec &mul_assign(const MyMat &A, const MyVec &x, MyVec &out); friend MyVec &mul_add_assign(const MyMat &A, const MyVec &x, const MyVec &y, MyVec &out); MyMat(string _name) : name(_name) { cout << "Creating MyMat " << _name << "\n"; } ~MyMat() { cout << "Destroying MyMat " << name << "\n"; } friend ostream &operator<<(ostream &s, const MyMat &x) { return s << x.name; } }; class MyVec { string name; public: friend class MyMat; friend MyVec &add_assign(const MyVec &x, const MyVec &y, MyVec &out); friend MyVec &mul_assign(const MyMat &A, const MyVec &x, MyVec &out); friend MyVec &mul_add_assign(const MyMat &A, const MyVec &x, const MyVec &y, MyVec &out); MyVec(string _name) : name(_name) { cout << "Creating MyVec " << _name << "\n"; } ~MyVec() { cout << "Destroying MyVec " << name << "\n"; } MyVec(const Vadd &vv) { add_assign(*vv.v1,*vv.v2,*this); } MyVec(const MVmul &mv) { mul_assign(*mv.m,*mv.v,*this); } MyVec(const MVmuladd &mv) { mul_add_assign(*mv.m,*mv.v1,*mv.v2,*this); } MyVec &operator=(const Vadd &vv) { return add_assign(*vv.v1,*vv.v2,*this); } MyVec &operator=(const MVmul &mv) { return mul_assign(*mv.m,*mv.v,*this); } MyVec &operator=(const MVmuladd &mv) { return mul_add_assign(*mv.m,*mv.v1,*mv.v2,*this); } friend ostream &operator<<(ostream &s, const MyVec &x) { return s << x.name; } }; inline MVmul operator*(const MyMat &mm, const MyVec &vv) { return MVmul(mm,vv); } inline MVmuladd operator+(const MVmul &mv, const MyVec &vv) { return MVmuladd(mv,vv); } inline Vadd operator+(const MyVec &v1, const MyVec &v2) { return Vadd(v1,v2); } Vadd::operator MyVec() { ostringstream oss; oss << "(" << *v1 << "+" << *v2 << ")"; MyVec *out = new MyVec(oss.str()); return add_assign(*v1,*v2,*out); } MVmul::operator MyVec() { ostringstream oss; oss << "(" << *m << "*" << *v << ")"; MyVec *out = new MyVec(oss.str()); return mul_assign(*m,*v,*out); } MVmuladd::operator MyVec() { ostringstream oss; oss << "(" << *m << "*" << *v1 << "+" << *v2 << ")"; MyVec *out = new MyVec(oss.str()); return mul_add_assign(*m,*v1,*v2,*out); } MyVec &add_assign(const MyVec &v1, const MyVec &v2, MyVec &out) { cout << "add_assign(" << v1 << "," << v2 << "," << out << ")\n"; return out; } MyVec &mul_assign(const MyMat &A, const MyVec &x, MyVec &out) { cout << "mul_assign(" << A << "," << x << "," << out << ")\n"; return out; } MyVec &mul_add_assign(const MyMat &A, const MyVec &x, const MyVec &y, MyVec &out) { cout << "mul_add_assign(" << A << "," << x << "," << y << "," << out << ")\n"; return out; } int main(int argc, char *argv[]) { MyVec u("u"), v("v"), w("w"), z("z"); MyMat A("A"); cout << "operation: w = u+v;\n"; w = u+v; cout << "operation: z = A*u+v;\n"; z = A*u+v; cout << "operation: z = A*(A*u+v)+z;\n"; z = A*(A*u+v)+z; cout << "operation: z = A*u + A*v + w + z;\n"; z = A*u + A*v + w + z; cout << "operation: A*(u+v) + w + z\n"; z = A*(u+v) + w + z; cout << "Done!\n"; }