
/*
 funny integrals:
   - Integrate(x,0,n)(1+x)*Cos((2*x)*Pi) with integer n
   - Integrate(x,0,n)(1-x)*Cos((2*x)*Pi) with integer n
 */

2 # AntiDeriv(_expr,_var)_Not(Contains(VarList(expr),var)) <--
    expr*var;
3 # AntiDeriv(_exx * _exy,_var)_Not(Contains(VarList(exx),var))  <--
    exx*AntiDeriv(exy,var);
3 # AntiDeriv(_exx * _exy,_var)_Not(Contains(VarList(exy),var))  <--
    exy*AntiDeriv(exx,var);
4 # AntiDeriv(_exx + _exy,_var) <-- AntiDeriv(exx,var)+AntiDeriv(exy,var);
4 # AntiDeriv(_exx - _exy,_var) <-- AntiDeriv(exx,var)-AntiDeriv(exy,var);
4 # AntiDeriv(- (_exx) ,_var) <-- -AntiDeriv(exx,var);
10 # AntiDeriv(UniVariate(_var,_first,_coefs),_var) <--
[
  Local(result);
  result:=FlatCopy(coefs);
  For(i:=1,i<=Length(result),i++)
  [
    result[i]:= result[i]/(first+i);
  ];
  UniVariate(var,first+1,result);
];

CanBeTerm(_expr,_var) <-- (MakeTerm(expr,var) != False);
10 # MakeTerm(     _var ^ _n, _var) <-- {var,n,1};
10 # MakeTerm(_a * (_var ^ _n), _var)_IsFreeOf(a,var) <-- {var,n,a};
10 # MakeTerm((_a * _var) ^ _n, _var)_IsFreeOf(a,var) <-- {var,n,a^n};
10 # MakeTerm(_var ^ _n * _a, _var)_IsFreeOf(a,var) <-- {var,n,a};
20 # MakeTerm(_expr,_var) <-- False;

11 # AntiDeriv(_exx / _exy,_var)_(CanBeTerm(exy,var)) <--
    [
      Local(term);
      term:=MakeTerm(exy,var);
      AntiDeriv(exx*term[1]^(-term[2]),var)/term[3];
    ];

11 # AntiDeriv(_exy,_var)_(CanBeTerm(exy,var)) <--
    [
      Local(term);
      term:=MakeTerm(exy,var);
      (term[1]^(term[2]+1))/(term[3]*(term[2]+1));
    ];


12 # AntiDeriv(_expr,_var)_CanBeUni(expr,var) <--
    NormalForm(AntiDeriv(Apply("MakeUni",{expr,var}),var));




/* Standard analytic function integration */


14 # AntiDeriv(Sin(_exx),_var)_
    (CanBeUni(exx,var) And Length(MakeUni(exx,var)[3]) <= 2) <--
[
  Local(uni);
  uni:=MakeUni(exx,var);
  (1/Coef(uni,1))*(-Cos(exx));
];
14 # AntiDeriv(Cos(_exx),_var)_
    (CanBeUni(exx,var) And Length(MakeUni(exx,var)[3]) <= 2) <--
[
  Local(uni);
  uni:=MakeUni(exx,var);
  (1/Coef(uni,1))*Sin(exx);
];
14 # AntiDeriv(Exp(_exx),_var)_
    (CanBeUni(exx,var) And Length(MakeUni(exx,var)[3]) <= 2) <--
[
  Local(uni);
  uni:=MakeUni(exx,var);
  (1/Coef(uni,1))*Exp(exx);
];

14 # AntiDeriv(Ln(_exx),_var)_
    (CanBeUni(exx,var) And Length(MakeUni(exx,var)[3]) <= 2) <--
[
  var*Ln(exx)-var;
];


14 # AntiDeriv(Abs(_exx),_var)_
     (CanBeUni(exx,var) And Length(MakeUni(exx,var)[3]) <= 2) <--
[
  Local(uni);
  uni:=MakeUni(exx,var);
  (Abs(exx)*exx)/(2*Coef(uni,1));
];

14 # AntiDeriv(if(_cond)(_body),_var) <--
     UnList({Atom("if"),cond,AntiDeriv(body,var)});
14 # AntiDeriv((_left) else (_right),_var) <--
     UnList({Atom("else"), (AntiDeriv(left,var)), (AntiDeriv(right,var)) } );


15 # AntiDeriv(_exx * _exy,_var)_(CanBeUni(exx,var) And
                            Type(Apply("AntiDeriv",{exy,var})) != "AntiDeriv") <--
[
  Local(anti);
  anti:=Apply("AntiDeriv",{exy,var});
  exx*anti-
    Apply("AntiDeriv",{anti*Deriv(var)exx,var});
];



15 # AntiDeriv(_exy * _exx,_var)_(CanBeUni(exx,var) And
                            Type(Apply("AntiDeriv",{exy,var})) != "AntiDeriv") <--
[
  Local(anti);
  anti:=Apply("AntiDeriv",{exy,var});
  exx*anti-
    Apply("AntiDeriv",{anti*Deriv(var)exx,var});
];

16 # AntiDeriv(_exy / _exx,_var)_(IsFreeOf(exx,var)) <--
(1/exx)*Apply("AntiDeriv",{exy,var});

20 # AntiDeriv(_exy / _exx,_var)_
        (CanBeUni(exx,var) And CanBeUni(exy,var) And Degree(exx,var) = 1 And Degree(exy,var) = 0) <--
[
  (exy/Coef(exx,var,1))*Ln(exx)-Apply("AntiDeriv",{Ln(exx)*Deriv(var)exy,var});
];

21 # AntiDeriv(_exy / _exx,_var)_
        (CanBeUni(exx,var) And CanBeUni(exy,var) And Degree(exx,var) > 1) <--
[
  Local(ee);
  ee:=Apart(exy/exx,var);
  Apply("AntiDeriv",{ee,var});
];

50 #  AntiDeriv(exp_HasTrig,_var) <--
[
  Apply("AntiDeriv",{TrigSimpCombine(exp),var});
/*  Apply("AntiDeriv",{Apply("TrigSimpCombine",{exp}),var});*/
];

RuleBase("Integrate",{var,from,to,expr});
HoldArg("Integrate",var);
/* HoldArg("Integrate",expr); */
Rule("Integrate",4,1,Type(Apply("AntiDeriv",{expr,var})) != "AntiDeriv")
[
  Local(ad,result);
  MacroLocal(var);
  ad:=Apply("AntiDeriv",{expr,var});
  MacroSet(var,to);
  result:=Eval(ad);
  MacroSet(var,from);
  result:=result-Eval(ad);
  result;
];

(Integrate(_var)_f) <-- AntiDeriv(f,var)+UniqueConstant();

10 # HasTrig(Sin(_x)) <-- True;
10 # HasTrig(Cos(_x)) <-- True;
20 # HasTrig(_x + _y) <-- HasTrig(x) Or HasTrig(y);
20 # HasTrig(_x - _y) <-- HasTrig(x) Or HasTrig(y);
20 # HasTrig(   - _y) <-- HasTrig(x) Or HasTrig(y);
20 # HasTrig(_x * _y) <-- HasTrig(x) Or HasTrig(y);
20 # HasTrig(_x / _y) <-- HasTrig(x) Or HasTrig(y);
20 # HasTrig(_x ^ _y) <-- HasTrig(x);
40 # HasTrig(_x) <-- False;
