Matrix result converting to quaternion and back has values flipped?
===

I have a 4x4 matrix (row-major) class and a quaternion class and I'm attempting to provide conversion methods that convert between the two representations for rotations.

This is my conversion function for converting from a quaternion to a matrix, where _2 is System.Math.Pow:

    /// <summary>
    /// Converts the quaternion to it's matrix representation.
    /// </summary>
    /// <returns>A matrix representing the quaternion.</returns>
    public Matrix ToMatrix()
    {
        return new Matrix(new double[,] {
            {
                _2(W) + _2(X) - _2(Y) - _2(Z),
                (2 * X * Y) - (2 * W * Z),
                (2 * X * Z) + (2 * W * Y),
                0
            },
            {
                (2 * X * Y) + (2 * W * Z),
                _2(W) - _2(X) + _2(Y) - _2(Z),
                (2 * Y * Z) + (2 * W * X),
                0
            },
            {
                (2 * X * Z) - (2 * W * Y),
                (2 * Y * Z) - (2 * W * X),
                _2(W) - _2(X) - _2(Y) + _2(Z),
                0
            },
            {
                0,
                0,
                0,
                1
            }
        });
    }

These are my two conversion functions for converting from a matrix to a quaternion.  Note that they both don't work when considering X rotation.


    /// <summary>
    /// Converts the matrix to a quaternion assuming the matrix purely
    /// represents rotation (any translation or scaling information will
    /// result in an invalid quaternion).
    /// </summary>
    /// <returns>A quaternion representing the rotation.</returns>
    public Quaternion ToQuaternion()
    {
        /* http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
            */
        double tr = this.m_Data[0, 0] + this.m_Data[1, 1] + this.m_Data[2, 2];
        if (tr > 0)
        {
            double s = _N2(tr + 1) * 2;
            return new Quaternion(
                (this.m_Data[2, 1] - this.m_Data[1, 2]) / s,
                (this.m_Data[0, 2] - this.m_Data[2, 0]) / s,
                (this.m_Data[1, 0] - this.m_Data[0, 1]) / s,
                0.25 * s
            );
        }
        else if ((this.m_Data[0, 0] > this.m_Data[1, 1]) && (this.m_Data[0, 0] > this.m_Data[2, 2]))
        {
            double s = _N2(1 + this.m_Data[0, 0] - this.m_Data[1, 1] - this.m_Data[2, 2]) * 2;
            return new Quaternion(
                0.25 * s,
                (this.m_Data[0, 1] + this.m_Data[1, 0]) / s,
                (this.m_Data[0, 2] + this.m_Data[2, 0]) / s,
                (this.m_Data[2, 1] - this.m_Data[1, 2]) / s
            );
        }
        else if (this.m_Data[1, 1] > this.m_Data[2, 2])
        {
            double s = _N2(1 + this.m_Data[1, 1] - this.m_Data[0, 0] - this.m_Data[2, 2]) * 2;
            return new Quaternion(
                (this.m_Data[0, 1] + this.m_Data[1, 0]) / s,
                0.25 * s,
                (this.m_Data[1, 2] + this.m_Data[2, 1]) / s,
                (this.m_Data[0, 2] - this.m_Data[2, 0]) / s
            );
        }
        else
        {
            double s = _N2(1 + this.m_Data[2, 2] - this.m_Data[0, 0] - this.m_Data[1, 1]) * 2;
            return new Quaternion(
                (this.m_Data[0, 2] + this.m_Data[2, 0]) / s,
                (this.m_Data[1, 2] + this.m_Data[2, 1]) / s,
                0.25 * s,
                (this.m_Data[1, 0] - this.m_Data[0, 1]) / s
            );
        }
    }

    /// <summary>
    /// This is a simpler form than above, but doesn't work for all values.  It exhibits the
    /// *same results* as ToQuaternion for X rotation however (i.e. both are invalid).
    /// </summary>
    public Quaternion ToQuaternionAlt()
    {
        double w = System.Math.Sqrt(1 + this.m_Data[0, 0] + this.m_Data[1, 1] + this.m_Data[2, 2]) / 2;
        return new Quaternion(
            (this.m_Data[2, 1] - this.m_Data[1, 2]) / (4 * w),
            (this.m_Data[0, 2] - this.m_Data[2, 0]) / (4 * w),
            (this.m_Data[1, 0] - this.m_Data[0, 1]) / (4 * w),
            w
        );
    }

**Now my test suite has a simple test like so:**

    [TestMethod]
    public void TestMatrixXA()
    {
        Matrix m = Matrix.CreateRotationX(45 / (180 / System.Math.PI));
        Assert.AreEqual<Matrix>(m, m.ToQuaternion().ToMatrix(), "Quaternion conversion was not completed successfully.");
    }

This is the result I get from the test suite:

    Expected:
    { 1, 0, 0, 0 }
    { 0, 0.707106781186548, -0.707106781186547, 0 }
    { 0, 0.707106781186547, 0.707106781186548, 0 }
    { 0, 0, 0, 1 }

    Actual:
    { 1, 0, 0, 0 }
    { 0, 0.707106781186547, 0.707106781186547, 0 }
    { 0, -0.707106781186547, 0.707106781186547, 0 }
    { 0, 0, 0, 1 }

You will note that the two values in the matrix are inverted.  I've tested it and upon each conversion back and forth (so .ToQuaternion().ToMatrix()) these fields are inverted.  i.e. If I do the quaternion / matrix conversion twice I get the correct matrix.

Since the difference between the correct value and the result is so simple, I'm assuming it's something simple like a negative sign being in the wrong place, but as I'm not an expert at matrix and quaternion math, I'm having trouble finding where the problem is.

*Does anyone know what's wrong with the math?*