public void PartitionOfUnity()
        {
            var k = new double[] { 0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 5 };
            Func <int, int, Func <double, double> > N = (i, p) => BSpline.Basis(k, i: i, p: p);
            var us    = Generate.LinearSpaced(100, 0, 4.9999);
            var p     = 2;
            var order = p + 1;

            foreach (var u in us)
            {
                var i = BSpline.KnotSpanFor(k, u);
                Enumerable.Range(i - p, order).Sum(j => N(j, p)(u)).Should().BeApproximately(1.0, 1e-5);
            }
        }
        public void Example2p1()
        {
            var k = new double[] { 0, 0, 0, 1, 1, 1 };

            BSpline.Basis(k, i: 0, p: 0).ShouldBe(u => 0, -10, 10); // -inf to inf
            BSpline.Basis(k, i: 1, p: 0).ShouldBe(u => 0, -10, -10);
            BSpline.Basis(k, i: 2, p: 0).ShouldBe(u => 1, 0, 1);
            BSpline.Basis(k, i: 3, p: 0).ShouldBe(u => 0, -10, -10);
            BSpline.Basis(k, i: 4, p: 0).ShouldBe(u => 0, -10, -10);

            BSpline.Basis(k, i: 0, p: 1).ShouldBe(u => 0, -10, 10);

            BSpline.Basis(k, i: 1, p: 1).ShouldBe(u => 1 - u, 0, 1);
            BSpline.Basis(k, i: 1, p: 1).ShouldBe(u => 0, -10, 0);
            BSpline.Basis(k, i: 1, p: 1).ShouldBe(u => 0, 1, 10);

            BSpline.Basis(k, i: 0, p: 2).ShouldBe(u => (1 - u).Pow(2), 0, 1);
            BSpline.Basis(k, i: 1, p: 2).ShouldBe(u => 2 * u * (1 - u), 0, 1);
            BSpline.Basis(k, i: 2, p: 2).ShouldBe(u => u * u, 0, 1);
        }
        public void Example2p2()
        {
            var k = new double[] { 0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 5 };
            Func <int, int, Func <double, double> > N = (i, p) => BSpline.Basis(k, i: i, p: p);

            N(0, 0).ShouldBe(u => 0, -10, 10);
            N(1, 0).ShouldBe(u => 0, -10, 10);

            N(2, 0).ShouldBe(u => 1, 0, 1);
            N(3, 0).ShouldBe(u => 1, 1, 2);
            N(4, 0).ShouldBe(u => 1, 2, 3);
            N(5, 0).ShouldBe(u => 1, 3, 4);
            N(6, 0).ShouldBe(u => 0, -10, 10);
            N(7, 0).ShouldBe(u => 1, 4, 5);
            N(8, 0).ShouldBe(u => 0, -10, 10);
            N(9, 0).ShouldBe(u => 0, -10, 10);

            N(0, 1).ShouldBe(u => 0, -10, 10);
            N(1, 1).ShouldBe(u => 1 - u, 0, 1);


            N(2, 1).ShouldBe(u => 0, -10, 0);
            N(2, 1).ShouldBe(u => u, 0, 1);
            N(2, 1).ShouldBe(u => 2 - u, 1, 2);
            N(2, 1).ShouldBe(u => 0, 2, 10);

            N(3, 1).ShouldBe(u => 0, -10, 1);
            N(3, 1).ShouldBe(u => (u - 1), 1, 2);
            N(3, 1).ShouldBe(u => 3 - u, 2, 3);
            N(3, 1).ShouldBe(u => 0, 3, 10);

            N(0, 2).ShouldBe(u => (1 - u).Pow(2), 0, 1);

            N(1, 2).ShouldBe(u => 2 * u - 3.0 / 2 * u * u, 0, 1);
            N(1, 2).ShouldBe(u => 0.5 * (2 - u).Pow(2), 1, 2);


            N(5, 2).ShouldBe(u => (u - 3).Pow(2), 3, 4);
            N(5, 2).ShouldBe(u => (5 - u).Pow(2), 4, 5);
        }
        public void BSplineBasisShouldWork()
        {
            var k = new double[] { 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 };

            BSpline.Basis(k, 0, 0, 0).Should().Be(1);
            BSpline.Basis(k, 0, 0, 0.09).Should().Be(1);
            BSpline.Basis(k, 0, 0, 1).Should().Be(0);

            BSpline.Basis(k, p: 0, i: 4, u: 0.4).Should().Be(1);
            BSpline.Basis(k, p: 0, i: 4, u: 0.49).Should().Be(1);
            BSpline.Basis(k, p: 0, i: 4, u: 0.5).Should().Be(0);

            BSpline.Basis(k, p: 1, i: 0, u: 0).Should().Be(0);
            BSpline.Basis(k, p: 1, i: 0, u: 0.05).Should().BeApproximately(0.5, 1e-5);
            BSpline.Basis(k, p: 1, i: 0, u: 0.1).Should().Be(1);
            BSpline.Basis(k, p: 1, i: 0, u: 0.15).Should().BeApproximately(0.5, 1e-5);
            BSpline.Basis(k, p: 1, i: 0, u: 0.2).Should().Be(0);

            BSpline.Basis(k, p: 1, i: 4, u: 0.4).Should().Be(0);
            BSpline.Basis(k, p: 1, i: 4, u: 0.5).Should().Be(1);
            BSpline.Basis(k, p: 1, i: 4, u: 0.6).Should().Be(0);
        }