




SolveNrUses(_fie,_var) <--  Count(VarListAll(fie),var);




10 # Solve(eq_IsList,var_IsList) <--
[
 If(Verbose, Echo({"Entering Solve"}));

  Local(result,i,j,nrvar,nreq,sub);
  nrvar:=Length(var);
  nreq:=Length(eq);
  result:={FlatCopy(var)};
  eq:=Simplify(eq);

  /* Loop over each variable, solving for it */

/* Echo({eq});  */

  For(i:=1,i<=nrvar,i++)
  [
    For(j:=1,j<=nreq,j++)
    [

      If(SolveNrUses(eq[j],var[i]) = 1,
         [
           sub:=Solve(eq[j],var[i]);
/*
DestructiveDelete(eq,j);
nreq--;
*/
 If(Verbose, Echo({"From ",eq[j]," it follows that ",var[i]," = ",sub})); 

/*           result:=Eliminate(var[i],sub,result);*/

	   result:=Simplify(Subst(var[i],sub)result);
/*           eq:=Eliminate(var[i],sub,eq); */
/*           eq[j] := (0 == 0);  */
           Local(k);
           For(k:=1,k<=Length(eq),k++)
           [
             Local(original);
             original:=eq[k];
             eq[k]:=Simplify(Subst(var[i],sub)eq[k]);
             If(Verbose, Echo({"   ",original," simplifies to ",eq[k]}));
           ];
/*           eq:=Simplify(Subst(var[i],sub)eq); */
/* Echo({eq});  */
           j:=nreq+1;
         ]);
    ];
  ];


  Local(zeroeq,tested);
  tested:={};
  zeroeq:=FillList(0==0,nreq);

  ApplyPure("MacroLocal",var);

  ForEach(item,result)
  [
    Apply(":=",{var,item});

    If(Simplify(Eval(eq)) = zeroeq,
    [
      DestructiveAppend(tested,item);
    ]);
  ];

/* Echo({"tested is ",tested});  */

 If(Verbose, Echo({"Leaving Solve"}));

  tested;
];


90 # Solve((left_IsList) == right_IsList,_var) <--
      Solve(Map("==",{left,right}),var);


100 # Solve(_left == _right,_var) <--
     SuchThat(left - right , 0 , var);

/* HoldArg("Solve",arg1); */
/* HoldArg("Solve",arg2); */


10 # ContainsExpression(_body,_body) <-- True;
15 # ContainsExpression(body_IsAtom,_expr) <-- False;
20 # ContainsExpression(body_IsFunction,_expr) <--
[
  Local(result,args);
  result:=False;
  args:=Tail(Listify(body));
  While(args != {})
  [
    result:=ContainsExpression(Head(args),expr);
    args:=Tail(args);
    if (result = True) (args:={});
  ];
  result;
];


SuchThat(_function,_var) <-- SuchThat(function,0,var);

10 # SuchThat(_left,_right,_var)_(left = var) <-- right;

/*This interferes a little with the multi-equation solver...
15 # SuchThat(_left,_right,_var)_CanBeUni(var,left-right) <--
     PSolve(MakeUni(left-right,var));
*/

20 # SuchThat(left_IsAtom,_right,_var) <-- var;

30 # SuchThat((_x) + (_y),_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right-y , var);
30 # SuchThat((_y) + (_x),_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right-y , var);

30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(r,var) <--
    SuchThat(r , right-I*i , var);
30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(i,var) <--
    SuchThat(i , right+I*r , var);

30 # SuchThat(_x * _y,_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right/y , var);
30 # SuchThat(_y * _x,_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right/y , var);

30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right^(1/y) , var);
30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(y,var) <--
    SuchThat(y , Ln(right)/Ln(x) , var);

30 # SuchThat(Sin(_x),_right,_var) <--
    SuchThat(x , ArcSin(right) , var);
30 # SuchThat(ArcSin(_x),_right,_var) <--
    SuchThat(x , Sin(right) , var);

30 # SuchThat(Cos(_x),_right,_var) <--
    SuchThat(x , ArcCos(right) , var);
30 # SuchThat(ArcCos(_x),_right,_var) <--
    SuchThat(x , Cos(right) , var);

30 # SuchThat(Tan(_x),_right,_var) <--
    SuchThat(x , ArcTan(right) , var);
30 # SuchThat(ArcTan(_x),_right,_var) <--
    SuchThat(x , Tan(right) , var);

30 # SuchThat(Exp(_x),_right,_var) <--
    SuchThat(x , Ln(right) , var);
30 # SuchThat(Ln(_x),_right,_var) <--
    SuchThat(x , Exp(right) , var);

30 # SuchThat(_x / _y,_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right*y , var);
30 # SuchThat(_y / _x,_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , y/right , var);

30 # SuchThat(- (_x),_right,_var) <--
    SuchThat(x , -right , var);

30 # SuchThat((_x) - (_y),_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , right+y , var);
30 # SuchThat((_y) - (_x),_right,_var)_ContainsExpression(x,var) <--
    SuchThat(x , y-right , var);

30 # SuchThat(Sqrt(_x),_right,_var) <--
    SuchThat(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})
/*block*/
[
  Local(result,adjust,delta);
  MacroLocal(variable);
  function:=N(function);
  adjust:= -function/Apply("D",{variable,function});
  delta:=10000;
  result:=initial;
  While (N(delta*Conjugate(delta)>accuracy*accuracy))
  [
    MacroSet(variable,result);
    delta:=N(adjust);
    result:=result+delta;
  ];
  result;
];
HoldArg("Newton",function);
HoldArg("Newton",variable);


