%mathpiper,def="MatchLinear;MatchPureSquared"

/*
todo:tk:MatchPureSquared() is in this file because it is grouped with MatchLinear in a
LocalSymbols() block.
*/

/* Def file definitions
MatchPureSquared
*/

/** MatchLinear(variable,expression)
 */
LocalSymbols(a,b)[

10 # MatchLinear(var_IsAtom,expr_CanBeUni(var)) <--
[
  Bind(expr,MakeUni(expr,var));
  MatchLinear(expr);
];
20 # MatchLinear(_var,_expr) <-- False;

10 # MatchLinear(_expr)_(Degree(expr,var)<2) <--
[
  Check(IsUniVar(expr), "Argument", PipeToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"}));

//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way?
//  Check(a = Hold(a), "Argument", PipeToString()(Echo({"Found bound variable a which should have been unbound, in MatchLinear: ", a, "=", Eval(a)})));
//  Check(b = Hold(b), "Argument", PipeToString()(Echo({"Found bound variable b which should have been unbound, in MatchLinear: ", b, "=", Eval(b)})));

  a := Coef(expr,1);
  b := Coef(expr,0);
  True;
];
20 # MatchLinear(_expr) <-- False;
UnFence("MatchLinear",1);
UnFence("MatchLinear",2);

/** MatchPureSquared(variable,expression) - matches expressions
 *  of the form a*x^2+b.
 */
10 # MatchPureSquared(var_IsAtom,_sign2,_sign0,expr_CanBeUni(var)) <--
[
  Bind(expr,MakeUni(expr,var));
  MatchPureSquared(expr,sign2,sign0);
];
20 # MatchPureSquared(_var,_sign2,_sign0,_expr) <-- False;

10 # MatchPureSquared(_expr,_sign2,_sign0)_(Degree(expr,var)=2 And
                                    Coef(expr,1) = 0 And
				    IsNumber(Coef(expr,0)) And
				    IsNumber(Coef(expr,2)) And
				    Coef(expr,0)*sign0 > 0 And
				    Coef(expr,2)*sign2 > 0
				    ) <--
[
  Check(IsUniVar(expr), "Argument", PipeToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"}));
//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way?
//  Check(a = Hold(a), "Invariant", "Found bound variable which should have been unbound, in MatchLinear");
//  Check(b = Hold(b), "Invariant", "Found bound variable which should have been unbound, in MatchLinear");
  a := Coef(expr,2);
  b := Coef(expr,0);
  True;
];
20 # MatchPureSquared(_expr,_sign2,_sign0) <-- False;
UnFence("MatchPureSquared",3);
UnFence("MatchPureSquared",4);

Matched'a() := a;
Matched'b() := b;



]; // LocalSymbols a,b


%/mathpiper



%mathpiper_docs,name="MatchLinear",categories="User Functions;Predicates"
*CMD MatchLinear --- match an expression to a polynomial of degree one in a variable
*STD
*CALL
	MatchLinear(x,expr)

*PARMS

{x} -- variable to express the univariate polynomial in

{expr} -- expression to match

*DESC

{MatchLinear} tries to match an expression to a linear (degree less than
two) polynomial. The function returns {True} if it could match, and
it stores the resulting coefficients in the variables "{a}" and "{b}"
as a side effect. The function calling this predicate should declare
local variables "{a}" and "{b}" for this purpose.
{MatchLinear} tries to match to constant coefficients which don't
depend on the variable passed in, trying to find a form "{a*x+b}"
with "{a}" and "{b}" not depending on {x} if {x} is given as the variable.

*E.G.

In> MatchLinear(x,(R+1)*x+(T-1))
Result: True;
In> {a,b};
Result: {R+1,T-1};
In> MatchLinear(x,Sin(x)*x+(T-1))
Result: False;
	
*SEE Integrate
%/mathpiper_docs