Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "maths.h"
- //This file is for +*/ operations. They work with tables of functions.
- //A and B are the Elements, a and b are the pointers they contain.
- #define set_op(TP0, TP1, OP) Element TP0##TP1##OP (Element A, Element B){ TP0* a = (TP0*)A.b; TP1* b = (TP1*)B.b;
- #define op(TP0, TP1, OP) TP0##TP1##OP
- //ADD
- //Numerical addition
- set_op(Number, Number, add)
- return new Number(a->num * b->den + b->num * a->den, a->den * b->den);
- }
- //Addition when nothing can be simplified
- set_op(Base, Base, add)
- Poly* r = new Poly();
- r->num.push_back(A);
- r->num.push_back(B);
- return r;
- }
- //Looks if any element of A can be added with B. If no, pushes B
- set_op(Poly, Base, add)
- Poly* r = new Poly(*a);
- for(unsigned i = 0; i < r->num.size(); i++){
- Element e = r->num[i] + B;
- if(e.b->type() != Base::poly){
- r->num[i] = e;
- return r;
- }
- }
- r->num.push_back(B);
- return r;
- }
- //does op(Poly, Base, add) for every element of A
- set_op(Poly, Poly, add)
- Element e = new Poly(*a);
- for(unsigned i = 0; i < b->num.size(); i++) e = e + b->num[i];
- return e;
- }
- //X+X=2X. Not really neccessary
- set_op(X, X, add)
- Mono* r = new Mono();
- r->num.push_back( new Number(2) );
- r->num.push_back( new X() );
- return r;
- }
- //Adds two monomials.
- set_op(Mono, Mono, add)
- if(a->den.size() || b->den.size()){
- Mono *an, *ad, *bn, *bd;
- Element AN, AD, BN, BD;
- AN = an = new Mono(); an->num = a->num;
- AD = ad = new Mono(); ad->num = a->den;
- BN = bn = new Mono(); bn->num = b->num;
- BD = bd = new Mono(); bd->num = b->den;
- Element e = AD + Element( new Number(-1) )*BD;
- //e = e.b->simplify();
- if(e.b->type() == Base::number && ((Number*)e.b)->num == 0)
- return (AN+BN)/AD;
- else
- return (AN*BD + BN*AD)/(AD*BD);
- }else{
- Element e = A / B;
- e = e.b->simplify();
- if(e.b->type() == Base::number)
- return (e + Element(new Number(1))) *B;
- else return op(Base, Base, add)(A, B);
- }
- }
- //Converts Base to Mono, then goes to previous. Only meant for X and Number
- set_op(Mono, Base, add)
- Mono* r = new Mono();
- r->num.push_back(B);
- return op(Mono, Mono, add)(r, A);
- }
- //op(Base, Base, add)
- set_op(X, Number, add)
- if(b->num == 0) return A;
- else return op(Base, Base, add)(A, B);
- }
- //op(Mono, Base, add)
- set_op(Mono, Number, add)
- if(b->num == 0) return A;
- else return op(Mono, Base, add)(A, B);
- }
- //op(Poly, Base, add)
- set_op(Poly, Number, add)
- if(b->num == 0) return A;
- else return op(Poly, Base, add)(A, B);
- }
- //a table of addition functions.
- //since addition (and multiplication) is symetrical, I only need a half of the table
- Operator addition[4][4] = {
- {op(Number, Number, add), 0 , 0 , 0 },
- { op(X, Number, add) , op(X, X, add) , 0 , 0 },
- { op(Mono, Number, add) , op(Mono, Base, add), op(Mono, Mono, add), 0 },
- { op(Poly, Number, add) , op(Poly, Base, add), op(Poly, Base, add), op(Poly, Poly, add)}
- };
- //MUL
- //Numerical multiplication
- set_op(Number, Number, mul)
- return new Number(a->num * b->num, a->den * b->den);
- }
- //Multiplication when nothing can be simplified
- set_op(Base, Base, mul)
- Mono* r = new Mono();
- r->num.push_back(A);
- r->num.push_back(B);
- return r;
- }
- //Searches the top for are any Number. If found, multiplies them. If not, pushes B
- //Due to op(Base, Number, div) no number will be in the bottom.
- set_op(Mono, Number, mul)
- Mono* r = new Mono(*a);
- for(unsigned i = 0; i < r->num.size(); i++){
- Element e = r->num[i] * B;
- if(e.b->type() != Base::mono){
- r->num[i] = e;
- return r;
- }
- }
- r->num.push_back(B);
- return r;
- }
- //Searches the bottom for any X. If found, replaces them with 1. If not pushes B on the top.
- //This may produce -1/1, but that's not really a problem..
- set_op(Mono, X, mul)
- Mono* r = new Mono(*a);
- for(unsigned i = 0; i < r->den.size(); i++){
- Element e = B / r->den[i];
- if(e.b->type() != Base::mono){
- r->den[i] = e;
- return r;
- }
- }
- r->num.push_back(B);
- return r;
- }
- //Multiplies two monomials
- set_op(Mono, Mono, mul)
- Element e = new Mono(*a);
- for(unsigned i = 0; i < b->num.size(); i++) e = e * b->num[i];
- for(unsigned i = 0; i < b->den.size(); i++) e = e / b->den[i];
- return e;
- }
- //Multiplies every element of A by B
- set_op(Poly, Base, mul)
- Element e = new Poly();
- for(unsigned i = 0; i < a->num.size(); i++) e = e + a->num[i]*B;
- return e;
- }
- //op(Base, Base, mul)
- set_op(X, Number, mul)
- if(b->num == 0) return B;
- else if(b->num == b->den) return A;
- else return op(Base, Base, mul)(A, B);
- }
- //op(Poly, Base, mul)
- set_op(Poly, Number, mul)
- if(b->num == 0) return B;
- else if(b->num == b->den) return A;
- else return op(Poly, Base, mul)(A, B);
- }
- //a table of multiplication functions.
- Operator multiplication[4][4] = {
- {op(Number, Number, mul), 0 , 0 , 0 },
- { op(X, Number, mul) , op(Base, Base, mul), 0 , 0 },
- { op(Mono, Number, mul) , op(Mono, X, mul) , op(Mono, Mono, mul), 0 },
- { op(Poly, Number, mul) , op(Poly, Base, mul), op(Poly, Base, mul), op(Poly, Base, mul)}
- };
- //DIV
- //Numerical division
- set_op(Number, Number, div)
- return new Number(a->num * b->den, b->num * a->den);
- }
- //X/X=1.
- set_op(X, X, div)
- return new Number(1);
- }
- //Base/Number = Base*(1/Number)
- set_op(Base, Number, div)
- return A * Element(new Number(b->den, b->num) );
- }
- //Base/Mono = Base*(1/Mono);
- set_op(Base, Mono, div)
- Mono* m = new Mono();
- m->num = b->den;
- m->den = b->num;
- return A * Element(m);
- }
- //Division when nothing can be simplified
- set_op(Base, Base, div)
- Mono* r = new Mono();
- r->num.push_back(A);
- r->den.push_back(B);
- return r;
- }
- //First checks if any element in top can be divided by B, then if any element in bottom can be multiplied by B
- set_op(Mono, Base, div)
- Mono* r = new Mono(*a);
- for(unsigned int i = 0; i < r->num.size(); i++){
- Element e = r->num[i] / B;
- if(e.b->type() != Base::mono){
- r->num[i] = e;
- return r;
- }
- }
- for(unsigned int i = 0; i < r->den.size(); i++){
- Element e = r->den[i] * B;
- if(e.b->type() != Base::mono){
- r->den[i] = e;
- return r;
- }
- }
- r->den.push_back(B);
- return r;
- }
- //Divides every element of A by B
- set_op(Poly, Base, div)
- Element e = new Poly();
- for(unsigned i = 0; i < a->num.size(); i++) e = e + a->num[i]/b;
- return e;
- }
- //a table of division functions.
- Operator division[4][4] = {
- {op(Number, Number, div), op(Base, Base, div), op(Base, Mono, div), op(Base, Base, div)},
- { op(Base, Number, div) , op(X, X, div) , op(Base, Mono, div), op(Base, Base, div)},
- { op(Base, Number, div) , op(Mono, Base, div), op(Base, Mono, div), op(Mono, Base, div)},
- { op(Base, Number, div) , op(Poly, Base, div), op(Poly, Base, div), op(Base, Base, div)}
- };
- // + * /
- //chooses a function form a table
- Element compute(Element a, Element b, Operator table[4][4]){
- a = a.b->simplify();
- b = b.b->simplify();
- if(Operator op = table[a.b->type()][b.b->type()]) return (*op)(a, b);
- else return (*table[b.b->type()][a.b->type()])(b, a);
- }
- Element operator + (Element a, Element b) {
- return compute(a, b, addition);
- }
- Element operator * (Element a, Element b) {
- return compute(a, b, multiplication);
- }
- Element operator / (Element a, Element b) {
- return compute(a, b, division);
- }
Advertisement
Add Comment
Please, Sign In to add comment