# How to deal with the condition $u_i=u_{i+1}$ in B-Spline basis function?

The defintion of B-Spline basis function as shown below:

Let $\vec{U}=\{u_0,u_1,\ldots,u_m\}$ a nondecreasing sequence of real numbers,i.e, $u_i\leq u_{i+1}\quad i=0,1,2\ldots m-1$

$$N_{i,0}(u)= \begin{cases} 1 & u_i\leq u<u_{i+1}\\ 0 & otherwise \end{cases}$$ $$N_{i,p}(u)=\frac{u-u_i}{u_{i+p}-u_i}N_{i,p-1}(u)+\frac{u_{i+p+1}-u}{u_{i+p+1}-u_{i+1}}N_{i+1,p-1}(u)$$

Although I know that Mathematica owns a built-in function BSplineBasis, however, I would like to write my auxiliay function $N_{i,p}(u)$ to learn the NURBS theory and Mathematica programming.

### NBSpline

Alogrithm: (*=======================Caculate N[i,0](u)================================*)
NBSpline[i_Integer, 0, u_Symbol, U : {Sequence[_] ..}] /;
i <= Length[U] - 2 :=
Piecewise[
{{1, U[[i + 1]] <= u < U[[i + 2]]},
{0, u < U[[i + 1]] || u >= U[[i + 2]]}}]

(*=======================Caculate N[i,p](u)================================*)

NBSpline[i_Integer, p_Integer, u_Symbol, U : {Sequence[_] ..}?OrderedQ] /;
p > 0 && i + p <= Length[U] - 2 :=
Module[{ini},
ini = Table[NBSpline[j, 0, u, U], {j, i, i + p}];
First@Simplify@
Nest[
Dot @@@
{Partition[#, 2, 1],
With[{m = i + p - Length@# + 1},
Table[
{(u - U[[k + 1]])/(U[[k + m + 1]] - U[[k + 1]]),
(U[[k + m + 2]] - u)/(U[[k + m + 2]] - U[[k + 2]])}, {k, i, i + Length@# - 2}]]}) &,
ini, p]
]


Test

NBSpline[1, 3, u, {1, 2, 3, 4, 5, 7}] // TraditionalForm In my function NBSpline I avoid the condition $u_i=u_{i+1}$, because it will occured the case $\frac{0}{0}$

In the book "The NURBS book", it defines this quotient $\frac{0}{0}$ to be zero.

### Question

How to deal with the condition $\frac{0}{0}$ that I sometimes need to set it to 0 ? Namely, How to deal with the condition $u_i=u_{i+1}$ in B-Spline basis function?

• Quiet@Block[{Indeterminate = 0}, 0/0]
– Kuba
Oct 15, 2014 at 12:29
• @Kuba,Thanks for your suggestion sincerely!:-) Then I execute your code, NBSpline[1, 3, u, {1, 1, 3, 4, 5, 7}] give a result without warning, however, NBSpline[1, 3, u, {1, 1, 1, 4, 5, 7}] and NBSpline[1, 3, u, {1, 1, 2, 2, 5, 7}] give the warning informtion Power::infy: Infinite expression 1/0 encountered. >>
– xyz
Oct 15, 2014 at 12:36
• Perhaps one should approach the problem of understanding $N_{i,p}$ by asking how to deal with the condition $u_i = u_{i+1}$. Redefining 0/0 is not the only way, and, given your comment, it's probably not a good way. Oct 15, 2014 at 12:47
• @MichaelE2, I got it!Thanks!
– xyz
Oct 15, 2014 at 12:56
• I guess you might be interested in this book: Curves and Surfaces for CAGD - A Practical Guide by Gerald Farin. Mar 27, 2016 at 9:11

Here is one way to deal with repeated entries in U. One can define a function to compute the coefficient, using one rule when $u_i = u_j$ and the general formula otherwise. One might put extra conditions on the patterns in coeff below, but if the function is called only within NBSpline, then one might assume the conditions are met.

ClearAll[coeff];
coeff[u_, i_, j_, U_] /; U[[i]] == U[[j]] := 0;
coeff[u_, i_, j_, U_] := (u - U[[i]])/(U[[j]] - U[[i]])


Then change the definition of NBSpline for p != 0 as follows.

NBSpline[i_Integer, p_Integer, u_Symbol,
U : {Sequence[_] ..}?OrderedQ] /; p > 0 && i + p <= Length[U] - 2 :=
Module[{ini}, ini = Table[NBSpline[j, 0, u, U], {j, i, i + p}];
First@Simplify@
With[{m = i + p - Length@# + 1},
Table[{
coeff[u, k + 1, k + m + 1, U],
coeff[u, k + m + 2, k + 2, U]},
{k, i, i + Length@# - 2}]]}) &, ini, p]]


Example:

NBSpline[1, 3, u, {1, 2, 2, 4, 5, 7}] The output of NBSpline[1, 3, u, {1, 2, 3, 4, 5, 7}] agrees with the output in the question.

P.S. The pattern U : {Sequence[_] ..}?OrderedQ is equivalent to U_List?OrderedQ. You might want a check that restricts U to be a list of numbers, since an ordered list of symbols such as {a, b, c} passes the OrderedQ test. The pattern U_?(VectorQ[#, NumericQ] && OrderedQ[#] &) is one way.

• +1,Good idea to deal with $u_i=u_{i+1}$:-)
– xyz
Oct 16, 2014 at 1:54
• BTW, Is it possible to make the order of Piecewise like $2\leq u<4, 4\leq u<5, 5\leq u<7$, rather than $5\leq u<7, 2\leq u<4, 4\leq u<5$?
– xyz
Oct 17, 2014 at 8:20
• The easiest way would be to sort it afterwards: MapAt[SortBy[Last], piecewisefn, 1], piecewisefn is the result of NBSpline. (Use SortBy[#, Last] & instead of SortBy[Last] if you're using V9 or earlier.) Oct 17, 2014 at 10:01
• I can't get the same result after running your code (version 12.0). Jan 29, 2020 at 7:17

Is this the behaviour you need?

## Solution

Unprotect[Power];
Power[0, -1] = 1
Protect[Power]


## Examples

0/0

0 ## Explanation ## Revert to normal

Unprotect[Power];
ClearAll[Power];
Protect[Power];

• The main probelm is the condition $u_i=u_{i+1}$, your solution can indeed deal with this case.Thanks sincerely!! +1:-) I have edited my question .
– xyz
Oct 15, 2014 at 13:00