%mathpiper,def="Modulo"

//Retract("Modulo",*);

0 # Modulo(_n,m_IsRationalOrNumber)_(m<0) <-- `Hold(Modulo(@n,@m));

1 # Modulo(n_IsNegativeInteger,m_IsPositiveInteger) <--
[
  Local(result);
  result := ModuloN(n,m);
  If (result < 0,result := result + m);
  result;
];
1 # Modulo(n_IsPositiveInteger,m_IsPositiveInteger) <-- ModuloN(n,m);
2 # Modulo(0,_m) <-- 0;
2 # Modulo(n_IsPositiveInteger,Infinity) <-- n;
3 # Modulo(n_IsInteger,m_IsInteger) <-- ModuloN(n,m);
4 # Modulo(n_IsNumber,m_IsNumber) <-- NonN(Modulo(Rationalize(n),Rationalize(m)));

5 # Modulo(n_IsRationalOrNumber,m_IsRationalOrNumber)/*_(n>0 And m>0)*/ <--
[
  Local(n1,n2,m1,m2);
  n1:=Numerator(n);
  n2:=Denominator(n);
  m1:=Numerator(m);
  m2:=Denominator(m);
  Modulo(n1*m2,m1*n2)/(n2*m2);
];

6 # Modulo(n_IsList,m_IsList) <-- Map("Modulo",{n,m});
7 # Modulo(n_IsList,_m) <-- Map("Modulo",{n,FillList(m,Length(n))});


30 # Modulo(n_CanBeUni,m_CanBeUni) <--
[
  Local(vars);
  vars:=VarList(n+m);
  NormalForm(Modulo(MakeUni(n,vars),MakeUni(m,vars)));
];


//Note:tk:moved here from univariate.rep.
0 # Modulo(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- n;
1 # Modulo(n_IsUniVar,m_IsUniVar)_
    (n[1] = m[1] And Degree(n) >= Degree(m)) <--
[
    UniVariate(n[1],0,
               UniDivide(Concat(ZeroVector(n[2]),n[3]),
                         Concat(ZeroVector(m[2]),m[3]))[2]);
];

10 # Modulo(n_CanBeUni, m_CanBeUni, vars_IsList)_(Length(vars)=1) <--
[
    NormalForm(Modulo(MakeUni(n,vars),MakeUni(m,vars)));
];

%/mathpiper

    %output,preserve="false"
      Result: True
.   %/output


%mathpiper_docs,name="Modulo",categories="User Functions;Numbers (Operations)"
*CMD Modulo --- Determine remainder of two mathematical objects after dividing one by the other

*STD
*CALL
	Modulo(x,y)
	Modulo(x,y,vars)

*PARMS

{x}, {y} -- integers or univariate polynomials
{vars}   -- a list containing the name of the (single) variable appearing in both polynomials

*DESC

{Modulo} returns the remainder after division.  {Modulo} is also defined for univariate polynomials.

If {Quotient(x,y)} returns "a" and {Modulo(x,y)} equals "b", then these numbers satisfy $x =a*y + b$ and $0 <= b < y$.

The second form of the function contains a third parameter, and is used in the special case where the 
the "divisor" polynomial contains an unbound "variable" which is really just a parameter.  
In that situation, MathPiper cannot distinguish the variable from the parameter, until you
specifically name the variable.  See the example below.

*E.G.

In> Quotient(5,3)
Result: 1;
In> Modulo(5,3)
Result: 2;
	
In> Modulo(x^2-5*x+2,x-1)
Result: -2
	
In> Modulo(x^2-5*x+2,x-k)
Result: x^2-5*x+2          
	    NOTE: answer is INCORRECT
In> Modulo(x^2-5*x+2,x-k,{x})
Result: (k-5)*k+2
	    NOTE: answer is now CORRECT

*SEE Gcd, Lcm, Quotient
%/mathpiper_docs

    %output,preserve="false"
      
.   %/output


