


RuleBase("D",{aVar,aFunc});
RuleBase("D",{aVar,aCount,aFunc});

Rule("D",2,1,IsList(aVar) And Not(IsList(aFunc)))
	Map("D",{aVar,FillList(aFunc, Length(aVar))});
Rule("D",2,1,IsList(aVar) And IsList(aFunc))
	Map("D",{aVar,aFunc});

Rule("D",2,3,True)
[
  MacroLocal(aVar);
  Apply("Deriv",{aVar,1,aFunc});
];

Rule("D",3,1,IsList(aVar) And Not(IsList(aFunc)))
	Map("D",{aVar,
                 FillList(aCount, Length(aVar)),
                 FillList(aFunc, Length(aVar))});
Rule("D",3,1,IsList(aVar) And IsList(aFunc))
	Map("D",{aVar,
                 FillList(aCount, Length(aVar)),
                 aFunc});
Rule("D",3,3,True)
[
  MacroLocal(aVar);
  Apply("Deriv",{aVar,aCount,aFunc});
];


HoldArg("D",aVar);
HoldArg("D",aFunc);

5 # (Deriv(_var,1)_func) <-- Deriv(var)func;
5 # (Deriv(_var,0)_func) <-- func;
10 # (Deriv(_var,n_IsPositiveInteger)_func) <-- Deriv(var)Deriv(var,n-1)func;
10 # (Deriv(_var,n_IsNegativeInteger)_func) <-- Check(0,"Negative derivative");

 
// Need to clean out Sec(x) and friends
0 # (Deriv(_var) (_var)) <-- 1;
1 # (Deriv(_var)func_IsAtom) <-- 0;
2 # (Deriv(_var)_x + _y) <--  (Deriv(var)x) + (Deriv(var)y);
2 # (Deriv(_var)- (_x) ) <-- -Deriv(var)x;
2 # (Deriv(_var)_x - _y) <--  (Deriv(var)x) - (Deriv(var)y);
2 # (Deriv(_var)_x * _y) <-- (x*Deriv(var)y) + (Deriv(var)x)*y;
2 # (Deriv(_var)Sin(_x)) <--  (Deriv(var)x)*Cos(x);
2 # (Deriv(_var)Sinh(_x))<--  (Deriv(var)x)*Cosh(x);
2 # (Deriv(_var)Cosh(_x))<--  (Deriv(var)x)*Sinh(x);
2 # (Deriv(_var)Cos(_x)) <-- -(Deriv(var)x)*Sin(x);
2 # (Deriv(_var)Csc(_x)) <--  -(Deriv(var)x)*Csc(x)*Cot(x);
2 # (Deriv(_var)Csch(_x)) <-- -(Deriv(var)x)*Csch(x)*Coth(x);
2 # (Deriv(_var)Sec(_x)) <--  (Deriv(var)x)*Sec(x)*Tan(x);
2 # (Deriv(_var)Sech(_x)) <-- -(Deriv(var)x)*Sech(x)*Tanh(x);
2 # (Deriv(_var)Cot(_x)) <--  -(Deriv(var)x)*Csc(x)^2;
2 # (Deriv(_var)Coth(_x)) <--  (Deriv(var)x)*Csch(x)^2;

2 # (Deriv(_var)Tan(_x)) <-- ((Deriv(var) x) / (Cos(x)^2));
2 # (Deriv(_var)Tanh(_x)) <-- (Deriv(var)x)*Sech(x)^2;

2 # (Deriv(_var)Exp(_x)) <--  (Deriv(var)x)*Exp(x);

// When dividing by a constant, this is faster
2 # (Deriv(_var)(_x / _y))_(IsFreeOf(var,y)) <-- (Deriv(var) x) / y;
3 # (Deriv(_var)(_x / _y)) <--
    (y* (Deriv(var) x) - x* (Deriv(var) y))/ (y^2);

2 # (Deriv(_var)Ln(_x)) <-- ((Deriv(var) x) / x);
2 # (Deriv(_var)(_x ^ _n))_(IsRationalOrNumber(n) Or IsFreeOf(var, n)) <--
    n * (Deriv(var) x) * (x ^ (n - 1));

2 # (Deriv(_var)(Abs(_x)))  <-- Sign(x)*(Deriv(var)x);
2 # (Deriv(_var)(Sign(_x))) <-- 0;

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

3 # (Deriv(_var)(_x ^ _n)) <-- (x^n)*Deriv(var)(n*Ln(x));

2 # (Deriv(_var)ArcSin(_x)) <-- (Deriv(var) x )/Sqrt(1 -(x ^ 2));
2 # (Deriv(_var)ArcCos(_x)) <-- -(Deriv(var)x)/Sqrt(1 -(x^2));
2 # (Deriv(_var)ArcTan(_x)) <-- (Deriv(var) x)/(1 + x^2);
2 # (Deriv(_var)Sqrt(_x)) <-- ((Deriv(var)x)/(2*Sqrt(x)));
2 # (Deriv(_var)Complex(_r,_i)) <-- Complex(Deriv(var)r,Deriv(var)i);

2 # (Deriv(_var)((_x)!)) <-- Gamma(1+x)*PolyGamma(0,1+x)*(Deriv(var) x);

LocalSymbols(var,var2,a,b,y)[
   2 # (Deriv(_var)Integrate(_var)(_y)) <-- y;
   2 # (Deriv(_var)Integrate(_var2,_a,_b)(y_IsFreeOf(var))) <-- 
         (Deriv(var)b)*(y Where var2 == b) -
         (Deriv(var)a)*(y Where var2 == a);
   3 # (Deriv(_var)Integrate(_var2,_a,_b)(_y)) <-- 
         (Deriv(var)b)*(y Where var2 == b) -
         (Deriv(var)a)*(y Where var2 == a) +
 	Integrate(var2,a,b) Deriv(var) y;
 ];



2 # (Deriv(_var)func_IsList)_(Not(IsList(var))) <--
    Map("Deriv",{FillList(var,Length(func)),func});


2 # (Deriv(_var)UniVariate(_var,_first,_coefs)) <--
[
  Local(result,m,i);
  result:=FlatCopy(coefs);
  m:=Length(result);
  For(i:=1,i<=m,i++)
  [
    result[i] := result[i] * (first+i-1);
  ];
  UniVariate(var,first-1,result);
];


RuleBase("Diverge", {aFunc, aBasis});
Rule("Diverge", 2, 1, IsList(aBasis) And IsList(aFunc) And Length(aBasis) = Length(aFunc))
	Add(Map("D", {aBasis,aFunc}));

RuleBase("Curl", {aFunc, aBasis});

Rule("Curl", 2, 1, Length(aBasis)=Length(aFunc))
	{
		Apply("D",{aBasis[2],aFunc[3]})-Apply("D",{aBasis[3],aFunc[2]}),
		Apply("D",{aBasis[3],aFunc[1]})-Apply("D",{aBasis[1],aFunc[3]}),
		Apply("D",{aBasis[1],aFunc[2]})-Apply("D",{aBasis[2],aFunc[1]})
	};


