In practice, I needs to define the UpValues
of a user-defined function. For instance, the operation of function like differential formula , expansion and so on.
Here, I will give a example that came from my answer. Please see here
Bernstein::invidx =
"Index `1` should be a non-negative machine-sized integer betwwen `2` and `3`.";
SyntaxInformation[Bernstein] = {"ArgumentsPattern" -> {_,_,_}};
SetAttributes[Bernstein, NumericFunction]
(*special cases*)
Bernstein[0, 0, u_?NumericQ] := 1
Bernstein[0, 0, u_Symbol] := 1
(*normal cases*)
Bernstein[deg_Integer?NonNegative, idx_Integer?NonNegative, u_?NumericQ] /;
idx <= deg && 0 <= u <= 1 :=
Binomial[deg, idx] u^idx (1 - u)^(deg - idx)
Bernstein[deg_Integer?NonNegative, idx_Integer?NonNegative, u_?NumericQ] /;
idx <= deg && (u > 1 || u < 0) := 0
Throw the error-informations
Bernstein[deg_Integer?NonNegative, idx_Integer?NonNegative, u_] /;
idx > deg && (Message[Bernstein::invidx, idx, 0, deg - 1]; False) := $Failed;
expr : Bernstein[deg_ /; ! (IntegerQ[deg] && NonNegative[deg]), idx_, u_] /;
(Message[Bernstein::intnm, Unevaluated[expr], 1]; False) := $Failed;
expr : Bernstein[deg_, idx_ /; ! (IntegerQ[idx] && NonNegative[idx]), u_] /;
(Message[Bernstein::intnm, Unevaluated[expr], 2]; False) := $Failed;
Bernstein[args___] /;
! ArgumentCountQ[Bernstein, Length[{args}], 3, 3] && False := $Failed;
The derivatives of Bernstein basis
Bernstein /: Derivative[0, 0, k_Integer?Positive][Bernstein] :=
Function[{deg, idx, u},
D[
deg (Bernstein[deg - 1, idx - 1, u] - Bernstein[deg - 1, idx, u]),
{u, k - 1}]
]
TEST
D[Bernstein[3, -2, x], x]
D[Bernstein[3, -2, x], {x, 2}]
Question
- How to deal with bad arguments when a function's
UpValues
is a pure-function? Namely, throw the error information and then return the symbol$Failed
.
Although Mr.Wizard given me a solution that using If[]
func /: Derivative[0, 0, 1][func] :=
Function[{n, i, x},
If[MatchQ[n, _Integer?NonNegative] && MatchQ[i, _Integer?NonNegative] && i <= n,
n (func[n - 1, i - 1, x] - func[n - 1, i, x]),
Defer@func[n, i, x]
]
]
However, which leads to another issue.
In fact, the built-in BSplineBasis[]
also ingnore this problem.
knots = {0, 0, 0, 0, 1/3, 2/3, 1, 1, 1, 1};
D[BSplineBasis[{3, knots}, 7, x], {x, 2}]