Guest User

Untitled

a guest
Jan 3rd, 2011
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.40 KB | None | 0 0
  1. #include "maths.h"
  2.  
  3. //This file is for +*/ operations. They work with tables of functions.
  4.  
  5. //A and B are the Elements, a and b are the pointers they contain.
  6. #define set_op(TP0, TP1, OP) Element TP0##TP1##OP (Element A, Element B){ TP0* a = (TP0*)A.b; TP1* b = (TP1*)B.b;
  7. #define op(TP0, TP1, OP) TP0##TP1##OP
  8.  
  9. //ADD
  10.  
  11. //Numerical addition
  12. set_op(Number, Number, add)
  13.     return new Number(a->num * b->den + b->num * a->den, a->den * b->den);
  14. }
  15.  
  16. //Addition when nothing can be simplified
  17. set_op(Base, Base, add)
  18.     Poly* r = new Poly();
  19.     r->num.push_back(A);
  20.     r->num.push_back(B);
  21.     return r;
  22. }
  23.  
  24. //Looks if any element of A can be added with B. If no, pushes B
  25. set_op(Poly, Base, add)
  26.     Poly* r = new Poly(*a);
  27.     for(unsigned i = 0; i < r->num.size(); i++){
  28.         Element e = r->num[i] + B;
  29.         if(e.b->type() != Base::poly){
  30.             r->num[i] = e;
  31.             return r;
  32.         }
  33.     }
  34.     r->num.push_back(B);
  35.     return r;
  36. }
  37.  
  38. //does op(Poly, Base, add) for every element of A
  39. set_op(Poly, Poly, add)
  40.     Element e = new Poly(*a);
  41.     for(unsigned i = 0; i < b->num.size(); i++) e = e + b->num[i];
  42.     return e;
  43. }
  44.  
  45. //X+X=2X. Not really neccessary
  46. set_op(X, X, add)
  47.     Mono* r = new Mono();
  48.     r->num.push_back( new Number(2) );
  49.     r->num.push_back( new X() );
  50.     return r;
  51. }
  52.  
  53. //Adds two monomials.
  54. set_op(Mono, Mono, add)
  55.     if(a->den.size() || b->den.size()){
  56.         Mono *an, *ad, *bn, *bd;
  57.         Element AN, AD, BN, BD;
  58.  
  59.         AN = an = new Mono();   an->num = a->num;
  60.         AD = ad = new Mono();   ad->num = a->den;
  61.         BN = bn = new Mono();   bn->num = b->num;
  62.         BD = bd = new Mono();   bd->num = b->den;
  63.  
  64.         Element e = AD + Element( new Number(-1) )*BD;
  65.         //e = e.b->simplify();
  66.         if(e.b->type() == Base::number && ((Number*)e.b)->num == 0)
  67.             return (AN+BN)/AD;
  68.         else
  69.             return (AN*BD + BN*AD)/(AD*BD);
  70.     }else{
  71.         Element e = A / B;
  72.         e = e.b->simplify();
  73.         if(e.b->type() == Base::number)
  74.             return (e + Element(new Number(1))) *B;
  75.         else return op(Base, Base, add)(A, B);
  76.     }
  77. }
  78.  
  79. //Converts Base to Mono, then goes to previous. Only meant for X and Number
  80. set_op(Mono, Base, add)
  81.     Mono* r = new Mono();
  82.     r->num.push_back(B);
  83.     return op(Mono, Mono, add)(r, A);
  84. }
  85.  
  86. //op(Base, Base, add)
  87. set_op(X, Number, add)
  88.     if(b->num == 0) return A;
  89.     else return op(Base, Base, add)(A, B);
  90. }
  91.  
  92. //op(Mono, Base, add)
  93. set_op(Mono, Number, add)
  94.     if(b->num == 0) return A;
  95.     else return op(Mono, Base, add)(A, B);
  96. }
  97.  
  98. //op(Poly, Base, add)
  99. set_op(Poly, Number, add)
  100.     if(b->num == 0) return A;
  101.     else return op(Poly, Base, add)(A, B);
  102. }
  103.  
  104. //a table of addition functions.
  105. //since addition (and multiplication) is symetrical, I only need a half of the table
  106. Operator addition[4][4] = {
  107.  
  108.     {op(Number, Number, add),          0         ,           0        ,           0        },
  109.     {  op(X, Number, add)   ,    op(X, X, add)   ,           0        ,           0        },
  110.     { op(Mono, Number, add) , op(Mono, Base, add), op(Mono, Mono, add),           0        },
  111.     { op(Poly, Number, add) , op(Poly, Base, add), op(Poly, Base, add), op(Poly, Poly, add)}
  112.  
  113. };
  114.  
  115. //MUL
  116.  
  117. //Numerical multiplication
  118. set_op(Number, Number, mul)
  119.     return new Number(a->num * b->num, a->den * b->den);
  120. }
  121.  
  122. //Multiplication when nothing can be simplified
  123. set_op(Base, Base, mul)
  124.     Mono* r = new Mono();
  125.     r->num.push_back(A);
  126.     r->num.push_back(B);
  127.     return r;
  128. }
  129.  
  130.  
  131. //Searches the top for are any Number. If found, multiplies them. If not, pushes B
  132.  //Due to op(Base, Number, div) no number will be in the bottom.
  133. set_op(Mono, Number, mul)
  134.     Mono* r = new Mono(*a);
  135.     for(unsigned i = 0; i < r->num.size(); i++){
  136.         Element e = r->num[i] * B;
  137.         if(e.b->type() != Base::mono){
  138.             r->num[i] = e;
  139.             return r;
  140.         }
  141.     }
  142.     r->num.push_back(B);
  143.     return r;
  144. }
  145.  
  146. //Searches the bottom for any X. If found, replaces them with 1. If not pushes B on the top.
  147.  //This may produce -1/1, but that's not really a problem..
  148. set_op(Mono, X, mul)
  149.     Mono* r = new Mono(*a);
  150.     for(unsigned i = 0; i < r->den.size(); i++){
  151.         Element e = B / r->den[i];
  152.         if(e.b->type() != Base::mono){
  153.             r->den[i] = e;
  154.             return r;
  155.         }
  156.     }
  157.     r->num.push_back(B);
  158.     return r;
  159. }
  160.  
  161. //Multiplies two monomials
  162. set_op(Mono, Mono, mul)
  163.     Element e = new Mono(*a);
  164.     for(unsigned i = 0; i < b->num.size(); i++) e = e * b->num[i];
  165.     for(unsigned i = 0; i < b->den.size(); i++) e = e / b->den[i];
  166.     return e;
  167. }
  168.  
  169. //Multiplies every element of A by B
  170. set_op(Poly, Base, mul)
  171.     Element e = new Poly();
  172.     for(unsigned i = 0; i < a->num.size(); i++) e = e + a->num[i]*B;
  173.     return e;
  174. }
  175.  
  176. //op(Base, Base, mul)
  177. set_op(X, Number, mul)
  178.     if(b->num == 0) return B;
  179.     else if(b->num == b->den) return A;
  180.     else return op(Base, Base, mul)(A, B);
  181. }
  182.  
  183. //op(Poly, Base, mul)
  184. set_op(Poly, Number, mul)
  185.     if(b->num == 0) return B;
  186.     else if(b->num == b->den) return A;
  187.     else return op(Poly, Base, mul)(A, B);
  188. }
  189.  
  190. //a table of multiplication functions.
  191. Operator multiplication[4][4] = {
  192.  
  193.     {op(Number, Number, mul),           0        ,           0        ,           0        },
  194.     {  op(X, Number, mul)   , op(Base, Base, mul),           0        ,           0        },
  195.     { op(Mono, Number, mul) ,  op(Mono, X, mul)  , op(Mono, Mono, mul),           0        },
  196.     { op(Poly, Number, mul) , op(Poly, Base, mul), op(Poly, Base, mul), op(Poly, Base, mul)}
  197.  
  198. };
  199.  
  200. //DIV
  201. //Numerical division
  202. set_op(Number, Number, div)
  203.     return new Number(a->num * b->den, b->num * a->den);
  204. }
  205.  
  206. //X/X=1.
  207. set_op(X, X, div)
  208.     return new Number(1);
  209. }
  210.  
  211. //Base/Number = Base*(1/Number)
  212. set_op(Base, Number, div)
  213.     return A * Element(new Number(b->den, b->num) );
  214. }
  215.  
  216. //Base/Mono = Base*(1/Mono);
  217. set_op(Base, Mono, div)
  218.     Mono* m = new Mono();
  219.     m->num = b->den;
  220.     m->den = b->num;
  221.     return A * Element(m);
  222. }
  223.  
  224. //Division when nothing can be simplified
  225. set_op(Base, Base, div)
  226.     Mono* r = new Mono();
  227.     r->num.push_back(A);
  228.     r->den.push_back(B);
  229.     return r;
  230. }
  231.  
  232. //First checks if any element in top can be divided by B, then if any element in bottom can be multiplied by B
  233. set_op(Mono, Base, div)
  234.     Mono* r = new Mono(*a);
  235.     for(unsigned int i = 0; i < r->num.size(); i++){
  236.         Element e = r->num[i] / B;
  237.         if(e.b->type() != Base::mono){
  238.             r->num[i] = e;
  239.             return r;
  240.         }
  241.     }
  242.     for(unsigned int i = 0; i < r->den.size(); i++){
  243.         Element e = r->den[i] * B;
  244.         if(e.b->type() != Base::mono){
  245.             r->den[i] = e;
  246.             return r;
  247.         }
  248.     }
  249.     r->den.push_back(B);
  250.     return r;
  251. }
  252.  
  253. //Divides every element of A by B
  254. set_op(Poly, Base, div)
  255.     Element e = new Poly();
  256.     for(unsigned i = 0; i < a->num.size(); i++) e = e + a->num[i]/b;
  257.     return e;
  258. }
  259.  
  260. //a table of division functions.
  261. Operator division[4][4] = {
  262.  
  263.     {op(Number, Number, div), op(Base, Base, div), op(Base, Mono, div), op(Base, Base, div)},
  264.     { op(Base, Number, div) ,    op(X, X, div)   , op(Base, Mono, div), op(Base, Base, div)},
  265.     { op(Base, Number, div) , op(Mono, Base, div), op(Base, Mono, div), op(Mono, Base, div)},
  266.     { op(Base, Number, div) , op(Poly, Base, div), op(Poly, Base, div), op(Base, Base, div)}
  267.  
  268. };
  269.  
  270. // + * /
  271.  
  272. //chooses a function form a table
  273. Element compute(Element a, Element b, Operator table[4][4]){
  274.     a = a.b->simplify();
  275.     b = b.b->simplify();
  276.  
  277.     if(Operator op = table[a.b->type()][b.b->type()]) return (*op)(a, b);
  278.     else return (*table[b.b->type()][a.b->type()])(b, a);
  279. }
  280.  
  281. Element operator + (Element a, Element b) {
  282.     return compute(a, b, addition);
  283. }
  284. Element operator * (Element a, Element b) {
  285.     return compute(a, b, multiplication);
  286. }
  287. Element operator / (Element a, Element b) {
  288.     return compute(a, b, division);
  289. }
Advertisement
Add Comment
Please, Sign In to add comment