


RuleBase("Solve",{ expr,var });
RuleBase("SimpleSolveAux",{left,right,var});
HoldArg("Solve",expr);
HoldArg("Solve",var);

Rule("Solve",2,0,
     Contains(VarList(expr),var) And Count(VarListAll(expr),var) = 1 And
     Type(expr) = "=")
     SimpleSolveAux(((expr)[[1]]) - ((expr)[[2]]) , 0 , var);

Rule("Solve",2,1, Type(expr) = "=" And
     Contains(VarList(expr),var) And CanBeUni(expr[[1]]-(expr[[2]]),var))
     PSolve(expr[[1]]-(expr[[2]]),var);

0 # SimpleSolveAux(_left,_right,_var)_(left = var) <-- right;
1 # SimpleSolveAux(left_IsAtom,_right,_var) <-- "NoSolution";

3 # SimpleSolveAux(_x + _y,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right-y , var);
3 # SimpleSolveAux(_y + _x,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right-y , var);

3 # SimpleSolveAux(Complex(_r,_i),_right,_var)_Contains(VarList(r),var) <--
    SimpleSolveAux(r , right-I*i , var);
3 # SimpleSolveAux(Complex(_r,_i),_right,_var)_Contains(VarList(i),var) <--
    SimpleSolveAux(i , right+I*r , var);

3 # SimpleSolveAux(_x * _y,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right/y , var);
3 # SimpleSolveAux(_y * _x,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right/y , var);

3 # SimpleSolveAux(_x ^ _y,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right^(1/y) , var);
3 # SimpleSolveAux(_x ^ _y,_right,_var)_Contains(VarList(y),var) <--
    SimpleSolveAux(y , Ln(right)/Ln(x) , var);

3 # SimpleSolveAux(Sin(_x),_right,_var) <--
    SimpleSolveAux(x , ArcSin(right) , var);
3 # SimpleSolveAux(ArcSin(_x),_right,_var) <--
    SimpleSolveAux(x , Sin(right) , var);

3 # SimpleSolveAux(Cos(_x),_right,_var) <--
    SimpleSolveAux(x , ArcCos(right) , var);
3 # SimpleSolveAux(ArcCos(_x),_right,_var) <--
    SimpleSolveAux(x , Cos(right) , var);

3 # SimpleSolveAux(Tan(_x),_right,_var) <--
    SimpleSolveAux(x , ArcTan(right) , var);
3 # SimpleSolveAux(ArcTan(_x),_right,_var) <--
    SimpleSolveAux(x , Tan(right) , var);

3 # SimpleSolveAux(Exp(_x),_right,_var) <--
    SimpleSolveAux(x , Ln(right) , var);
3 # SimpleSolveAux(Ln(_x),_right,_var) <--
    SimpleSolveAux(x , Exp(right) , var);

3 # SimpleSolveAux(_x / _y,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right*y , var);
3 # SimpleSolveAux(_y / _x,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , y/right , var);

3 # SimpleSolveAux(- (_x),_right,_var) <--
    SimpleSolveAux(x , -right , var);

3 # SimpleSolveAux(_x - _y,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , right+y , var);
3 # SimpleSolveAux(_y - _x,_right,_var)_Contains(VarList(x),var) <--
    SimpleSolveAux(x , y-right , var);

3 # SimpleSolveAux(Sqrt(_x),_right,_var) <--
    SimpleSolveAux(x , right^2 , var);


Function("SolveMatrix",{matrix,vector})
[
  Local(perms,indices,inv,det,n);
  n:=Length(matrix);
  indices:=Table(i,i,1,n,1);
  perms:=Permutations(indices);
  inv:=ZeroVector(n);
  det:=0;
  ForEach(item,perms)
  [
    Local(i,lc);
    lc := LeviCivita(item);
    det:=det+Factorize(i,1,n,matrix[[i]][[item[[i]] ]])* lc;
    For(i:=1,i<=n,i++)
        [
         inv[[i]] := inv[[i]]+
           Factorize(j,1,n,
           If(item[[j]] =i,vector[[j ]],matrix[[j]][[item[[j]] ]]))*lc;
        ];
  ];
  Check(det != 0, "Zero determinant");
  (1/det)*inv;
];



Function("Newton",{function,variable,initial,accuracy})
[
  Local(result,adjust,delta);
  MacroLocal(variable);
  function:=Apply("Eval",{function});
  adjust:= -function/Apply("D",{variable,function});
  delta:=10000;
  result:=initial;
  While (MathAbs(delta)>accuracy)
  [
    MacroSet(variable,result);
    delta:=N(Eval(adjust));
    result:=N(result+delta);
  ];
  result;
];
HoldArg("Newton",function);
HoldArg("Newton",variable);


