'Evaluate the basis of the BSpline or its derivative.
If lower or upper is specified, then only
the [lower:upper] elements of the basis are returned.
INPUTS:
x     -- x values at which to evaluate the basis element
i     -- which element of the BSpline to return
d     -- the order of derivative
lower -- optional lower limit of the set of basis
elements
upper -- optional upper limit of the set of basis
elements
OUTPUTS: y
y  -- value of d-th derivative of the basis elements
of the BSpline at specified x values'

def basis(self, x, d=0, lower=None, upper=None):

    x = np.asarray(x)
    _shape = x.shape
    if (_shape == ()):
        x.shape = (1,)
    x.shape = (np.product(_shape, axis=0),)
    if (upper is None):
        upper = (self.tau.shape[0] - self.m)
    if (lower is None):
        lower = 0
    upper = min(upper, (self.tau.shape[0] - self.m))
    lower = max(0, lower)
    d = np.asarray(d)
    if (d.shape == ()):
        v = _hbspline.evaluate(x, self.tau, self.m, int(d), lower, upper)
    else:
        if (d.shape[0] != 2):
            raise ValueError('if    d    is    not    an    integer,    expecting    a    jx2                                                                                array    with    first    row    indicating    order                                                                                of    derivative,    second    row    coefficient    in    front.')
        v = 0
        for i in range(d.shape[1]):
            v += (d[(1, i)] * _hbspline.evaluate(x, self.tau, self.m, d[(0, i)], lower, upper))
    v.shape = (((upper - lower),) + _shape)
    if (upper == (self.tau.shape[0] - self.m)):
        v[(-1)] = np.where(np.equal(x, self.tau[(-1)]), 1, v[(-1)])
    return v
