Real IntpBSplineUniform3<Real>::operator() (int dx, int dy, int dz,
    Real x, Real y, Real z)
{
    mBase[0] = (int)Math<Real>::Floor(x);
    mBase[1] = (int)Math<Real>::Floor(y);
    mBase[2] = (int)Math<Real>::Floor(z);
    for (int dim = 0; dim < 3; ++dim)
    {
        if (mOldBase[dim] != mBase[dim])
        {
            // Switch to new local grid.
            for (int k = 0; k < 3; ++k)
            {
                mOldBase[k] = mBase[k];
                mGridMin[k] = mBase[k] - 1;
                mGridMax[k] = mGridMin[k] + mDegree;
            }

            // Fill in missing grid data if necessary.
            if (mEvaluateCallback)
            {
                EvaluateUnknownData();
            }

            ComputeIntermediate();
            break;
        }
    }

    SetPolynomial(dx, x - mBase[0], mPoly[0]);
    SetPolynomial(dy, y - mBase[1], mPoly[1]);
    SetPolynomial(dz, z - mBase[2], mPoly[2]);

    int index[3] = { dx, dy, dz };
    int delta[2] = { dx, mDp1*dy };
    Real result = (Real)0.0;
    for (int k = index[0] + mDp1*(index[1] + mDp1*index[2]); k < mDp1ToN; ++k)
    {
        result +=  mPoly[0][index[0]]*mPoly[1][index[1]]*
            mPoly[2][index[2]]*mInter[k];

        if (++index[0] <= mDegree)
        {
            continue;
        }
        index[0] = dx;
        k += delta[0];

        if (++index[1] <= mDegree)
        {
            continue;
        }
        index[1] = dy;
        k += delta[1];

        index[2]++;
    }
    return result;
}
Real IntpBSplineUniform2<Real>::operator() (int iDx, int iDy, Real fX,
    Real fY)
{
    m_aiBase[0] = (int)Math<Real>::Floor(fX);
    m_aiBase[1] = (int)Math<Real>::Floor(fY);
    for (int iDim = 0; iDim < 2; iDim++)
    {
        if (m_aiOldBase[iDim] != m_aiBase[iDim])
        {
            // switch to new local grid
            for (int k = 0; k < 2; k++)
            {
                m_aiOldBase[k] = m_aiBase[k];
                m_aiGridMin[k] = m_aiBase[k] - 1;
                m_aiGridMax[k] = m_aiGridMin[k] + m_iDegree;
            }

            // fill in missing grid data if necessary
            if (m_oEvaluateCallback)
            {
                EvaluateUnknownData();
            }

            ComputeIntermediate();
            break;
        }
    }

    SetPolynomial(iDx,fX-m_aiBase[0],m_aafPoly[0]);
    SetPolynomial(iDy,fY-m_aiBase[1],m_aafPoly[1]);

    int aiI[2] = { iDx, iDy };
    int iIncr1 = iDx;
    Real fResult = (Real)0.0;
    for (int k = aiI[0]+m_iDp1*aiI[1]; k < m_iDp1ToN; k++)
    {
        fResult += m_aafPoly[0][aiI[0]]*m_aafPoly[1][aiI[1]]*m_afInter[k];

        if (++aiI[0] <= m_iDegree)
        {
            continue;
        }
        aiI[0] = iDx;
        k += iIncr1;

        aiI[1]++;
    }
    return fResult;
}
Real IntpBSplineUniform1<Real>::operator() (int iDx, Real fX)
{
    m_aiBase[0] = (int)Math<Real>::Floor(fX);
    if (m_aiOldBase[0] != m_aiBase[0])
    {
        // switch to new local grid
        m_aiOldBase[0] = m_aiBase[0];
        m_aiGridMin[0] = m_aiBase[0] - 1;
        m_aiGridMax[0] = m_aiGridMin[0] + m_iDegree;

        // fill in missing grid data if necessary
        if (m_oEvaluateCallback)
        {
            EvaluateUnknownData();
        }

        ComputeIntermediate();
    }

    SetPolynomial(iDx,fX-m_aiBase[0],m_aafPoly[0]);

    Real fResult = (Real)0.0;
    for (int k = iDx; k <= m_iDegree; k++)
    {
        fResult += m_aafPoly[0][k]*m_afInter[k];
    }
    return fResult;
}
Real IntpBSplineUniform1<Real>::operator() (int dx, Real x)
{
	mBase[0] = (int)Math<Real>::Floor(x);
	if (mOldBase[0] != mBase[0])
	{
		// Switch to new local grid.
		mOldBase[0] = mBase[0];
		mGridMin[0] = mBase[0] - 1;
		mGridMax[0] = mGridMin[0] + mDegree;

		// Fill in missing grid data if necessary.
		if (mEvaluateCallback)
		{
			EvaluateUnknownData();
		}

		ComputeIntermediate();
	}

	SetPolynomial(dx, x - mBase[0], mPoly[0]);

	Real result = (Real)0;
	for (int k = dx; k <= mDegree; ++k)
	{
		result += mPoly[0][k]*mInter[k];
	}
	return result;
}
Real IntpBSplineUniform2<Real>::operator() (Real x, Real y)
{
    mBase[0] = (int)Math<Real>::Floor(x);
    mBase[1] = (int)Math<Real>::Floor(y);
    for (int dim = 0; dim < 2; ++dim)
    {
        if (mOldBase[dim] != mBase[dim])
        {
            // Switch to new local grid.
            for (int k = 0; k < 2; ++k)
            {
                mOldBase[k] = mBase[k];
                mGridMin[k] = mBase[k] - 1;
                mGridMax[k] = mGridMin[k] + mDegree;
            }

            // Fill in missing grid data if necessary.
            if (mEvaluateCallback)
            {
                EvaluateUnknownData();
            }

            ComputeIntermediate();
            break;
        }
    }

    SetPolynomial(0, x - mBase[0], mPoly[0]);
    SetPolynomial(0, y - mBase[1], mPoly[1]);

    int index[2] = { 0, 0 };
    Real result = (Real)0;
    for (int k = index[0] + mDp1*index[1]; k < mDp1ToN; ++k)
    {
        result += mPoly[0][index[0]]*mPoly[1][index[1]]*mInter[k];

        if (++index[0] <= mDegree)
        {
            continue;
        }
        index[0] = 0;

        index[1]++;
    }
    return result;
}
Real IntpBSplineUniform4<Real>::operator() (Real fX, Real fY, Real fZ,
    Real fW)
{
    m_aiBase[0] = (int)Math<Real>::Floor(fX);
    m_aiBase[1] = (int)Math<Real>::Floor(fY);
    m_aiBase[2] = (int)Math<Real>::Floor(fZ);
    m_aiBase[3] = (int)Math<Real>::Floor(fW);
    for (int iDim = 0; iDim < 4; iDim++)
    {
        if (m_aiOldBase[iDim] != m_aiBase[iDim])
        {
            // switch to new local grid
            for (int k = 0; k < 4; k++)
            {
                m_aiOldBase[k] = m_aiBase[k];
                m_aiGridMin[k] = m_aiBase[k] - 1;
                m_aiGridMax[k] = m_aiGridMin[k] + m_iDegree;
            }

            // fill in missing grid data if necessary
            if (m_oEvaluateCallback)
            {
                EvaluateUnknownData();
            }

            ComputeIntermediate();
            break;
        }
    }

    SetPolynomial(0,fX-m_aiBase[0],m_aafPoly[0]);
    SetPolynomial(0,fY-m_aiBase[1],m_aafPoly[1]);
    SetPolynomial(0,fZ-m_aiBase[2],m_aafPoly[2]);
    SetPolynomial(0,fW-m_aiBase[3],m_aafPoly[3]);

    int aiI[4] = { 0, 0, 0, 0 };
    Real fResult = (Real)0.0;
    for (int k = 0; k < m_iDp1ToN; k++)
    {
        fResult += m_aafPoly[0][aiI[0]]*m_aafPoly[1][aiI[1]]*
            m_aafPoly[2][aiI[2]]*m_aafPoly[3][aiI[3]]*m_afInter[k];

        if (++aiI[0] <= m_iDegree)
        {
            continue;
        }
        aiI[0] = 0;

        if (++aiI[1] <= m_iDegree)
        {
            continue;
        }
        aiI[1] = 0;

        if (++aiI[2] <= m_iDegree)
        {
            continue;
        }
        aiI[2] = 0;

        aiI[3]++;
    }
    return fResult;
}