10 of 14
deleted 10 characters in body
xyz
  • 605
  • 4
  • 38
  • 117

Checking the argument of user-defined function Bernstein

Today, I answered a question of mine that asked two month ago. Please see here

Now I would like to add the argument checking in this function. Then I used a method that Mr.Wizard answered

###Requirement for the arguments of Bernstein[n,i,u]

  • n must be a integer like $1,2,3,...$;
  • i must be a integer like $1,2,3,...$;
  • i should between 0 and n-1.

For instance, the built-in BernsteinBasis gives the warning information as below:

BernsteinBasis[1.2, 2, 3]

BernsteinBasis::intnm: Non-negative machine-sized integer expected at position 1 in BernsteinBasis[1.2,2,3]. >>

BernsteinBasis[1.2, 2.1, 3]

BernsteinBasis::intnm: Non-negative machine-sized integer expected at position 1 in BernsteinBasis[1.2,2.1,3]. >>

BernsteinBasis::intnm: Non-negative machine-sized integer expected at position 2 in BernsteinBasis[1.2,2.1,3]. >>

BernsteinBasis[4, 5, u]

BernsteinBasis::invidx2:Index 5 should be a machine-sized integer between 0 and 4. >>

###checkArgs

Attributes[checkArgs] = {HoldAll};
(*check the number of arguments*)
checkArgs [func_[args___]] /; Length@{args} != 3 := 
  Message[func::argrx, func, Length@{args}, 3]

(*check the type of the first arguments*)
checkArgs [func_[a_, b_, c_]] /; ! MatchQ[a, _Integer?NonNegative] := 
  Message[func::intnm, func[a, b, c], 1]

(*check the type of second arguments*)
checkArgs [func_[a_, b_, c_]] /; ! MatchQ[b, _Integer?NonNegative] := 
  Message[func::intnm, func[a, b, c], 2]

checkArgs[func_[a_, b_, c_]] /; ! (0 <= b <= a - 1) := 
  Message[func::invidx, b, 0, a - 1]

(*other valid cases*)
checkArgs[other_] := True

###Main implementation

Bernstein::invidx = 
 "The index `1` should be a non-negtive machine-sized integer betwwen `2` and `3`.";

 SetAttributes[Bernstein, {Listable, NHoldAll, NumericFunction}]
(*special cases*)

Bernstein[n_, i_, u_]?checkArgs /; i < 0 || i > n := 0

Bernstein[0, 0, u_]?checkArgs := 1

Bernstein[n_, i_, u_?NumericQ]?checkArgs := 
 Binomial[n, i] u^i (1 - u)^(n - i)

(*expansion of the basis of Bernstein*)
Bernstein /: PiecewiseExpand[Bernstein[n_, i_, u_]] := 
 Piecewise[
  {{Binomial[n, i] u^i (1 - u)^(n - i), 0 <= u <= 1}, 
   {0, u > 1 || u < 0}}]

(*the derivatives of the basis of Bernstein*)
Bernstein /: Derivative[0, 0, k_Integer?Positive][Bernstein] := 
 Function[{n, i, u}, 
  D[
   n (Bernstein[n - 1, i - 1, u] - Bernstein[n - 1, i, u]), 
   {u, k - 1}]
 ]

However, it gives the following information.

$RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

$RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

$RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

General::stop: Further output of $RecursionLimit::reclim will be suppressed during this calculation. >>

Bernstein::intnm: Non-negative machine-sized integer expected at position >Bernstein[n_,i_,u_] in 1. >>

xyz
  • 605
  • 4
  • 38
  • 117