@@ -452,7 +452,7 @@ BOOST_AUTO_TEST_CASE(deBoorBasis_degree0)
452452 const int degree = 0 ;
453453 Eigen::VectorXd knots (3 );
454454 knots << 0 ., 2 ., 3 .;
455- Eigen::MatrixXd basis (1 , 1 );
455+ Eigen::MatrixXd basis (Eigen::MatrixXd::Zero ( 1 , 1 ) );
456456
457457 deBoorBasis (degree, knots, 0 , 0 ., basis);
458458 BOOST_CHECK_SMALL (basis (0 , 0 ) - 1 ., 1e-8 );
@@ -476,7 +476,7 @@ BOOST_AUTO_TEST_CASE(deBoorBasis_degree1)
476476 const int degree = 1 ;
477477 Eigen::VectorXd knots (5 );
478478 knots << 0 ., 2 ., 3 ., 5 ., 5.5 ;
479- Eigen::MatrixXd basis (2 , 2 );
479+ Eigen::MatrixXd basis (Eigen::MatrixXd::Zero ( 2 , 2 ) );
480480
481481 // Evaluate between 2 and 3
482482 deBoorBasis (degree, knots, 1 , 2 ., basis);
@@ -510,7 +510,7 @@ BOOST_AUTO_TEST_CASE(deBoorBasis_degree3)
510510 const int degree = 3 ;
511511 Eigen::VectorXd knots (9 );
512512 knots << 0 ., 2 ., 3 ., 5 ., 5.5 , 8 ., 8.5 , 10 ., 11.5 ;
513- Eigen::MatrixXd basis (4 , 4 );
513+ Eigen::MatrixXd basis (Eigen::MatrixXd::Zero ( 4 , 4 ) );
514514
515515 deBoorBasis (degree, knots, 3 , 5 ., basis);
516516 BOOST_CHECK_SMALL (
@@ -583,6 +583,127 @@ BOOST_AUTO_TEST_CASE(deBoorBasis_degree3)
583583 getAbsoluteBasis (4 , basis, 4 , degree) - bsplineBasis (4 , degree, 8 ., knots), 1e-8 );
584584}
585585
586+ // Test deBoorBasisFull with a knot vector only defined
587+ // on one span.
588+ // This should give the same result than deBoorBasis function.
589+ BOOST_AUTO_TEST_CASE (deBoorBasisFull_degree2_minimal_knot)
590+ {
591+ using pinocchio::internal::deBoorBasis;
592+ using pinocchio::internal::deBoorFullBasis;
593+
594+ const int degree = 2 ;
595+ Eigen::VectorXd knots (6 );
596+ // Defined between 3 and 5
597+ knots << 0 ., 2 ., 3 ., 5 ., 5.5 , 8.3 ;
598+ Eigen::MatrixXd basis_ref (Eigen::MatrixXd::Zero (3 , 3 ));
599+ Eigen::MatrixXd basis (3 , 3 );
600+
601+ deBoorBasis (degree, knots, 2 , 3 ., basis_ref);
602+ deBoorFullBasis (degree, knots, 3 ., basis);
603+ BOOST_CHECK (basis_ref.isApprox (basis));
604+
605+ deBoorBasis (degree, knots, 2 , 4 ., basis_ref);
606+ deBoorFullBasis (degree, knots, 4 ., basis);
607+ BOOST_CHECK (basis_ref.isApprox (basis));
608+
609+ deBoorBasis (degree, knots, 2 , 5 ., basis_ref);
610+ deBoorFullBasis (degree, knots, 5 ., basis);
611+ BOOST_CHECK (basis_ref.isApprox (basis));
612+ }
613+
614+ // Test deBoorBasisFull with a knot vector allowing to compute
615+ // more basis function than deBoorBasis.
616+ // We compare it to deBoorBasis called on the right span.
617+ BOOST_AUTO_TEST_CASE (deBoorBasisFull_degree3_nominal_knot)
618+ {
619+ using pinocchio::internal::deBoorBasis;
620+ using pinocchio::internal::deBoorFullBasis;
621+
622+ const int degree = 2 ;
623+ Eigen::VectorXd knots (8 );
624+ // Defined between 3 and 8.3
625+ knots << 0 ., 2 ., 3 ., 5 ., 5.5 , 8.3 , 9 ., 11.3 ;
626+ Eigen::MatrixXd basis_ref (Eigen::MatrixXd::Zero (3 , 3 ));
627+ Eigen::MatrixXd basis (3 , 5 );
628+
629+ deBoorFullBasis (degree, knots, 3 ., basis);
630+ deBoorBasis (degree, knots, 2 , 3 ., basis_ref);
631+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 0 )));
632+ BOOST_CHECK ((basis.block <3 , 2 >(0 , 3 ).isZero ()));
633+
634+ deBoorFullBasis (degree, knots, 4 ., basis);
635+ deBoorBasis (degree, knots, 2 , 4 ., basis_ref);
636+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 0 )));
637+ BOOST_CHECK ((basis.block <3 , 2 >(0 , 3 ).isZero ()));
638+
639+ deBoorFullBasis (degree, knots, 5 ., basis);
640+ deBoorBasis (degree, knots, 3 , 5 ., basis_ref);
641+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 1 )));
642+ BOOST_CHECK ((basis.col (0 ).isZero ()));
643+ BOOST_CHECK ((basis.col (4 ).isZero ()));
644+
645+ deBoorFullBasis (degree, knots, 5.3 , basis);
646+ deBoorBasis (degree, knots, 3 , 5.3 , basis_ref);
647+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 1 )));
648+ BOOST_CHECK ((basis.col (0 ).isZero ()));
649+ BOOST_CHECK ((basis.col (4 ).isZero ()));
650+
651+ deBoorFullBasis (degree, knots, 5.5 , basis);
652+ deBoorBasis (degree, knots, 4 , 5.5 , basis_ref);
653+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 2 )));
654+ BOOST_CHECK ((basis.block <3 , 2 >(0 , 0 ).isZero ()));
655+
656+ deBoorFullBasis (degree, knots, 8 ., basis);
657+ deBoorBasis (degree, knots, 4 , 8 ., basis_ref);
658+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 2 )));
659+ BOOST_CHECK ((basis.block <3 , 2 >(0 , 0 ).isZero ()));
660+
661+ deBoorFullBasis (degree, knots, 8.3 , basis);
662+ deBoorBasis (degree, knots, 4 , 8.3 , basis_ref);
663+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 2 )));
664+ BOOST_CHECK ((basis.block <3 , 2 >(0 , 0 ).isZero ()));
665+ }
666+
667+ // Test deBoorBasisFull with a knot vector with element of multiplicity 3.
668+ // This should create division by 0 issue managed by the algorithm.
669+ BOOST_AUTO_TEST_CASE (deBoorBasisFull_degree3_multiplicity_knot)
670+ {
671+ using pinocchio::internal::deBoorBasis;
672+ using pinocchio::internal::deBoorFullBasis;
673+
674+ const int degree = 2 ;
675+ Eigen::VectorXd knots (9 );
676+ // Defined between 0 and 2
677+ knots << 0 ., 0 ., 0 ., 1 ., 1 ., 1 ., 2 ., 2 ., 2 .;
678+ Eigen::MatrixXd basis_ref (Eigen::MatrixXd::Zero (3 , 3 ));
679+ Eigen::MatrixXd basis (3 , 6 );
680+
681+ deBoorFullBasis (degree, knots, 0 ., basis);
682+ deBoorBasis (degree, knots, 2 , 0 ., basis_ref);
683+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 0 )));
684+ BOOST_CHECK ((basis.block <3 , 3 >(0 , 3 ).isZero ()));
685+
686+ deBoorFullBasis (degree, knots, 0.5 , basis);
687+ deBoorBasis (degree, knots, 2 , 0.5 , basis_ref);
688+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 0 )));
689+ BOOST_CHECK ((basis.block <3 , 3 >(0 , 3 ).isZero ()));
690+
691+ deBoorFullBasis (degree, knots, 1 ., basis);
692+ deBoorBasis (degree, knots, 5 , 1 ., basis_ref);
693+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 3 )));
694+ BOOST_CHECK ((basis.block <3 , 3 >(0 , 0 ).isZero ()));
695+
696+ deBoorFullBasis (degree, knots, 1.5 , basis);
697+ deBoorBasis (degree, knots, 5 , 1.5 , basis_ref);
698+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 3 )));
699+ BOOST_CHECK ((basis.block <3 , 3 >(0 , 0 ).isZero ()));
700+
701+ deBoorFullBasis (degree, knots, 2 ., basis);
702+ deBoorBasis (degree, knots, 5 , 2 ., basis_ref);
703+ BOOST_CHECK (basis_ref.isApprox (basis.block <3 , 3 >(0 , 3 )));
704+ BOOST_CHECK ((basis.block <3 , 3 >(0 , 0 ).isZero ()));
705+ }
706+
586707// Test cumulativeBasisDerivative against bsplineBasisDerivative
587708BOOST_AUTO_TEST_CASE (cumulativeBasisDerivative)
588709{
@@ -592,7 +713,7 @@ BOOST_AUTO_TEST_CASE(cumulativeBasisDerivative)
592713 const int degree = 3 ;
593714 Eigen::VectorXd knots (9 );
594715 knots << 0 ., 2 ., 3 ., 5 ., 5.5 , 8 ., 8.5 , 10 ., 11.5 ;
595- Eigen::MatrixXd basis (4 , 4 );
716+ Eigen::MatrixXd basis (Eigen::MatrixXd::Zero ( 4 , 4 ) );
596717
597718 auto computeDerivative = [knots](int start, double q) {
598719 Eigen::VectorXd res (4 );
@@ -673,7 +794,7 @@ BOOST_AUTO_TEST_CASE(cumulativeBasisDerivative2)
673794 const int degree = 3 ;
674795 Eigen::VectorXd knots (9 );
675796 knots << 0 ., 2 ., 3 ., 5 ., 5.5 , 8 ., 8.5 , 10 ., 11.5 ;
676- Eigen::MatrixXd basis (4 , 4 );
797+ Eigen::MatrixXd basis (Eigen::MatrixXd::Zero ( 4 , 4 ) );
677798
678799 auto computeDerivative2 = [knots](int start, double q) {
679800 Eigen::VectorXd res (4 );
0 commit comments