using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Azimuth.SparseLinearAlgebra;

namespace Azimuth.UnitTests.SparseLinearAlgebra
{
    public class GivensRotationTests : UnitTestSharp.TestFixture
    {
        public class FindRotationTests : UnitTestSharp.TestFixture
        {
            public void b_gr_a()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(3, 4, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(0.6, c);
                CheckEqual(-.8, s);
            }

            public void a_gr_b()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(4, 3, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(.8, c);
                CheckEqual(-.6, s);
            }

            public void a_0()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(0, 3, out r, out c, out s);

                CheckEqual(3, r);
                CheckEqual(0, c);
                CheckEqual(-1, s);
            }

            public void b_0()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(3, 0, out r, out c, out s);

                CheckEqual(3, r);
                CheckEqual(1, c);
                CheckEqual(0, s);
            }

            public void Both0()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(0, 0, out r, out c, out s);

                CheckEqual(0, r);
                CheckEqual(1, c);
                CheckEqual(0, s);
            }

            public void b_0_a_neg()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(-3, 0, out r, out c, out s);

                CheckEqual(3, r);
                CheckEqual(-1, c);
                CheckEqual(0, s);
            }

            public void a_0_b_neg()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(0, -3, out r, out c, out s);

                CheckEqual(3, r);
                CheckEqual(0, c);
                CheckEqual(1, s);
            }

            public void b_neg_gr_a_neg()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(-3, -4, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(-0.6, c);
                CheckEqual(.8, s);
            }

            public void b_neg_gr_a()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(-3, 4, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(-0.6, c);
                CheckEqual(-.8, s);
            }

            public void b_gr_a_neg()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(3, -4, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(0.6, c);
                CheckEqual(.8, s);
            }

            public void a_neg_gr_b_neg()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(-4, -3, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(-.8, c);
                CheckEqual(.6, s);
            }

            public void a_neg_gr_b()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(-4, 3, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(-.8, c);
                CheckEqual(-.6, s);
            }

            public void a_gr_b_neg()
            {
                Scalar r, c, s;
                GivensRotation.FindRotation(4, -3, out r, out c, out s);

                CheckEqual(5, r);
                CheckEqual(.8, c);
                CheckEqual(.6, s);
            }
        }

        public class ApplyRotationTests : UnitTestSharp.TestFixture
        {
            public void Basic_1()
            {
                Scalar a = 5;
                Scalar b = 3;

                GivensRotation.ApplyRotation(ref a, ref b, 0.8, -0.6);

                CheckEqual(5.8, a);
                CheckEqual(-0.6, b);
            }

            public void Basic_2()
            {
                Scalar a = 5;
                Scalar b = 0;

                GivensRotation.ApplyRotation(ref a, ref b, 0.8, -0.6);

                CheckEqual(4, a);
                CheckEqual(-3, b);
            }
        }

        public class TurnunderTests : UnitTestSharp.TestFixture
        {
            public void Basic()
            {
                Scalar c1 = 0.1;
                Scalar c2 = 0.2;
                Scalar c3 = 0.3;
                
                Scalar s1 = -Math.Sqrt(1 - c1 * c1);
                Scalar s2 = -Math.Sqrt(1 - c2 * c2);
                Scalar s3 = -Math.Sqrt(1 - c3 * c3);

                GivensRotation.Turnunder(ref c1, ref s1, ref c2, ref s2, ref c3, ref s3);

                CheckEqual(-0.321710829612886, c3);
                CheckEqual(0.946837970357013, s3);

                CheckEqual(-0.159831504234677, c1);
                CheckEqual(0.987144310754046, s1);

                CheckEqual(-0.157112961781263, c2);
                CheckEqual(0.987580638348241, s2);
            }

            public void Signs()
            {
                Scalar c1 = 0.674199862463242;
                Scalar c2 = 0.377964473009227;
                Scalar c3 = 0.980066577841242;

                Scalar s1 = -0.738548945875996;
                Scalar s2 = -0.925820099772551;
                Scalar s3 = 0.198669330795061;

                GivensRotation.Turnunder(ref c1, ref s1, ref c2, ref s2, ref c3, ref s3);

                CheckEqual(-0.964643085423153, c3);
                CheckEqual(-0.263559704327690, s3);

                CheckEqual(0.716218354603956, c1);
                CheckEqual(0.697876255885241, s1);

                CheckEqual(-0.200090067645788, c2);
                CheckEqual(0.979777507819762, s2);
            }
        }

        public class FuseTests : UnitTestSharp.TestFixture
        {
            public void Basic()
            {
                Scalar c1 = 0.8;
                Scalar s1 = -0.6;

                Scalar c2 = -0.5;
                Scalar s2 = Math.Sqrt(1 - c2 * c2);

                Scalar cOut, sOut;
                GivensRotation.Fuse(c1, s1, c2, s2, out cOut, out sOut);

                CheckEqual(0.119615242270663, cOut);
                CheckEqual(0.992820323027551, sOut);
            }
        }

        public class TurnunderMerge_UphillGivensSequence : UnitTestSharp.TestFixture
        {
            public void Basic_x21()
            {
                DenseVector _x2cos = new Scalar[] { 0.2, -0.5 };
                DenseVector _x2sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), };

                DenseVector _x1cos = new Scalar[] { -0.6, };
                DenseVector _x1sin = new Scalar[] { -Math.Sqrt(1 - 0.6*0.6) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x2cos, ref _x2sin, ref _x1cos, ref _x1sin, c, s);

                DenseVector expected_x2cos = new Scalar[] { 0.604930765133789, 0.879161429622670, };
                DenseVector expected_x2sin = new Scalar[] { 0.796278072908358, 0.476524060949521,  };

                DenseVector expected_x1cos = new Scalar[] { 0.176081369517586 };
                DenseVector expected_x1sin = new Scalar[] { -0.984375614950315 };

                CheckEqual(expected_x2cos, _x2cos);
                CheckEqual(expected_x2sin, _x2sin);

                CheckEqual(expected_x1cos, _x1cos);
                CheckEqual(expected_x1sin, _x1sin);
            }

            public void Basic_x32()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8*0.8)};

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1-0.9*0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s);

                DenseVector expected_x3cos = new Scalar[] { 0.604930765133789, -0.7656914528, -0.9949270005, };
                DenseVector expected_x3sin = new Scalar[] { 0.796278072908358, 0.6432080528, -0.1005995216, };

                DenseVector expected_x2cos = new Scalar[] { 0.176081369517586, 0.8096674122, };
                DenseVector expected_x2sin = new Scalar[] { -0.984375614950315, 0.5868889858, };

                CheckEqual(expected_x3cos, _x3cos);
                CheckEqual(expected_x3sin, _x3sin);

                CheckEqual(expected_x2cos, _x2cos);
                CheckEqual(expected_x2sin, _x2sin);
            }

            public void Basic_x43()
            {
                DenseVector _x4cos = new Scalar[] { 0.674199862463242, 0.730296743340222, 0.801783725737273, 0.894427190999916 };
                DenseVector _x4sin = new Scalar[] { -0.738548945875996, -0.683130051063973, -0.597614304667197, -0.447213595499958 };

                DenseVector _x3cos = new Scalar[] { 0.377964473009227, 0.272165526975909, 0.141421356237310 };
                DenseVector _x3sin = new Scalar[] { -0.925820099772551, -0.962250448649376, -0.989949493661167 };

                Scalar c = 0.980066577841242;
                Scalar s = 0.198669330795061;

                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x4cos, ref _x4sin, ref _x3cos, ref _x3sin, c, s);

                DenseVector expected_x4cos = new Scalar[] { 0.716218354603956, -0.753477896929329, 0.772333934060259, -0.983612445181156 };
                DenseVector expected_x4sin = new Scalar[] { 0.697876255885241, 0.657473238116165, 0.635216730178766, -0.180295750600916 };

                DenseVector expected_x3cos = new Scalar[] { -0.200090067645788, -0.0199643993896671, 0.364129745514120 };
                DenseVector expected_x3sin = new Scalar[] { 0.979777507819762, 0.9998006915165691, 0.931348231561011 };

                CheckEqual(expected_x4cos, _x4cos);
                CheckEqual(expected_x4sin, _x4sin);

                CheckEqual(expected_x3cos, _x3cos);
                CheckEqual(expected_x3sin, _x3sin);
            }

            public void StartingIndexTooLarge_1()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, 3, 0, 1);

            }

            public void StartingIndexTooLarge_2()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, 0, 2, 1);

            }

            public void StartingIndexNegative_1()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, -1, 0, 1);
            }

            public void StartingIndexNegative_2()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, 0, -1, 1);
            }

            public void RunningLengthTooLong()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, 0, 0, 3);
            }

            public void RunningLength0()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                var expected_x3cos = _x3cos.Clone();
                var expected_x3sin = _x3sin.Clone();
                var expected_x2cos = _x2cos.Clone();
                var expected_x2sin = _x2sin.Clone();

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, 0, 0, 0);

                CheckEqual(expected_x3cos, _x3cos);
                CheckEqual(expected_x3sin, _x3sin);
                CheckEqual(expected_x2cos, _x2cos);
                CheckEqual(expected_x2sin, _x2sin);
            }

            public void RunningLengthNegative()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s, 0, 0, -1);
            }

            public void GivensLengthMismatch_SameSize()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, 1.0, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9), 0 };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s);
            }

            public void GivensLengthMismatch_ParentTooLarge()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6,  };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s);
            }

            public void GivensLengthMismatch_ChildLarger()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, 1.0, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9), 0 };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s);
            }

            public void GivensLengthMismatch_Parent()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6), Math.Sqrt(1 - 0.9 * 0.9) };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s);
            }

            public void GivensLengthMismatch_Child()
            {
                DenseVector _x3cos = new Scalar[] { 0.2, -0.5, 0.8 };
                DenseVector _x3sin = new Scalar[] { Math.Sqrt(1 - 0.2 * 0.2), Math.Sqrt(1 - 0.5 * 0.5), -Math.Sqrt(1 - 0.8 * 0.8) };

                DenseVector _x2cos = new Scalar[] { -0.6, -0.9, };
                DenseVector _x2sin = new Scalar[] { -Math.Sqrt(1 - 0.6 * 0.6),  };

                Scalar c = 0.1;
                Scalar s = Math.Sqrt(1 - 0.1 * 0.1);

                CheckThrow(typeof(Exception));
                GivensRotation.TurnunderMerge_UphillGivensSequence(ref _x3cos, ref _x3sin, ref _x2cos, ref _x2sin, c, s);
            }
        }

        public class FindDownhillGivensSeriesTests : UnitTestSharp.TestFixture
        {
            public void x1()
            {
                DenseVector column = new Scalar[] { 5, };
                var cosine = new DenseVector(0);
                var sine = new DenseVector(0);

                var expectedColumn = column.Clone();
                var expectedCosine = cosine.Clone();
                var expectedSine = sine.Clone();

                GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine);

                CheckEqual(expectedColumn, column);
                CheckEqual(expectedCosine, cosine);
                CheckEqual(expectedSine, sine);
            }

            public void x2()
            {
                DenseVector column = new Scalar[] { 3, 4, };
                var cosine = new DenseVector(1);
                var sine = new DenseVector(1);

                var expectedColumn = column.Clone();
                
                GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine);

                DenseVector expectedCosine = new Scalar[] { 0.6, };
                DenseVector expectedSine = new Scalar[] { -0.8, };

                CheckEqual(expectedColumn, column);
                CheckEqual(expectedCosine, cosine);
                CheckEqual(expectedSine, sine);
            }

            public void x4()
            {
                DenseVector column = new Scalar[] { 1, 2, 3, 4, };
                var cosine = new DenseVector(3);
                var sine = new DenseVector(3);

                var expectedColumn = column.Clone();

                GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, 0, 3);

                DenseVector expectedCosine = new Scalar[] { 0.182574185835055, 0.371390676354104, 0.6, };
                DenseVector expectedSine = new Scalar[] { -0.983192080250175 , -0.928476690885259, -0.8, };

                CheckEqual(expectedColumn, column);
                CheckEqual(expectedCosine, cosine);
                CheckEqual(expectedSine, sine);
            }

            public void Length_1()
           {
                var column = new Scalar[] { -4, 3, 3, 4, };
                var cosine = new DenseVector(3);
                var sine = new DenseVector(3);
                
                var expectedCosine = cosine.Clone();
                var expectedSine = sine.Clone();
                expectedCosine[0] = -0.8;
                expectedSine[0] = -0.6;

                var expectedColumn = column.Clone();

                var magnitude = GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, 0, 1);

                CheckEqual(5, magnitude);
                CheckEqual(expectedColumn, column);
                CheckEqual(expectedCosine, cosine);
                CheckEqual(expectedSine, sine);
            }

            class RangeCheckingTests : UnitTestSharp.TestFixture
            {
                DenseVector column;
                DenseVector cosine;
                DenseVector sine;

                DenseVector expectedColumn;

                public override void TestSetup()
                {
                    column = new Scalar[] { 1, 2, 3, 4, };
                    cosine = new DenseVector(3);
                    sine = new DenseVector(3);

                    expectedColumn = column.Clone();
                }

                public void StartingIndexColumn_Negative()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, -1, 0, 0, 3);
                }

                public void StartingIndexColumn_TooLarge()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 1, 0, 0, 3);
                }

                public void StartingIndexCosine_Negative()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, -1, 0, 3);
                }

                public void StartingIndexCosine_TooLarge()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 1, 0, 3);
                }

                public void StartingIndexSine_Negative()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, -1, 3);
                }

                public void StartingIndexSine_TooLarge()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, 1, 3);
                }

                public void Length_Negative()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, 0, -1);
                }

                public void Length_TooLong()
                {
                    CheckThrow(typeof(Exception));
                    GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, 0, 5);
                }

                public void Length_0()
                {
                    var expectedCosine = cosine.Clone();
                    var expectedSine = sine.Clone();

                    var magnitude = GivensRotation.FindDownhillGivensSeries_Column(column, ref cosine, ref sine, 0, 0, 0, 0);

                    // Or should it be column[startingIndex]?
                    // That wouldn't necessarily be positive.
                    CheckEqual(0, magnitude);

                    CheckEqual(expectedColumn, column);
                    CheckEqual(expectedCosine, cosine);
                    CheckEqual(expectedSine, sine);
                }
            }
        }
    }
}