test_vector.cpp

Back to Vectors

test/pastel/sys/

// Description: Testing for Vector
// DocumentationOf: vector.h

#include "test/test_init.h"

#include "pastel/sys/rational.h"
#include "pastel/sys/vector.h"

namespace
{

    using Real = Rational<integer>;
    //using Real = real;

    template <typename Type, integer N>
    void someFunction(const Tuple<Type, N>& jorma)
    {
    }

    template <integer N>
    void testNullPointerStatic()
    {
        Vector<Real, N> au2(0);
        Vector<Real, N> au3(0.0);

        Vector<float, N> af2(0);
        Vector<float, N> af3(0.0);

        Vector<int, N> ai1(0);
        Vector<int, N> ai2(0.0);
    }

    template <integer N>
    void testNullPointer()
    {
        integer n = (N == Dynamic) ? 3 : N;

        Tuple<float, N> t(ofDimension(n), 0);

        Vector<float, N> c(ofDimension(n));

        Vector<float, N> af1(c + c);
        Vector<float, N> af5(ofDimension(n), 0);
        Vector<float, N> af6(ofDimension(n), 0.0);

        Vector<int, N> ai5(ofDimension(n), 0);
        Vector<int, N> ai6(ofDimension(n), 0.0);
    }

}

TEST_CASE("VectorBasic (VectorBasic)")
{

    PASTEL_STATIC_ASSERT(sizeof(Vector<Real, 3>) == 3 * sizeof(Real));
    PASTEL_STATIC_ASSERT(sizeof(Vector<integer, 3>) == 3 * sizeof(integer));

    Vector<Real, 3> a(1, 2, 3);
    REQUIRE(a[0] == 1);
    REQUIRE(a[1] == 2);
    REQUIRE(a[2] == 3);

    Vector<Real, 3> b = Vector<Real, 3>(4, 5, 6);
    REQUIRE(b[0] == 4);
    REQUIRE(b[1] == 5);
    REQUIRE(b[2] == 6);

    Vector<Real, 3> c(b);
    REQUIRE(c[0] == 4);
    REQUIRE(c[1] == 5);
    REQUIRE(c[2] == 6);

    a = b;
    REQUIRE(a[0] == 4);
    REQUIRE(a[1] == 5);
    REQUIRE(a[2] == 6);

    a = 3;
    REQUIRE(a[0] == 3);
    REQUIRE(a[1] == 3);
    REQUIRE(a[2] == 3);

    someFunction(asTuple(a));

    a.assign({ 1, 2, 3});
    REQUIRE(a[0] == 1);
    REQUIRE(a[1] == 2);
    REQUIRE(a[2] == 3);

    a = { 1, 2, 3 };

    Vector<float> cd(ofDimension(2));
}

TEST_CASE("VectorLowDimensional (VectorLowDimensional)")
{
    // Tests the low-dimension specific
    // member functions.

    {
        Vector<Real, 1> a = Vector<Real, 1>(1);
        REQUIRE(a[0] == 1);

        a.set(4);
        REQUIRE(a[0] == 4);

        a = 7;
        REQUIRE(a[0] == 7);

        Vector<Real, 1> b(8);
        REQUIRE(b[0] == 8);

        b.set(9);
        REQUIRE(b[0] == 9);
    }
    {
        Vector<Real, 2> a = Vector<Real, 2>(1, 2);
        REQUIRE(a[0] == 1);
        REQUIRE(a[1] == 2);

        a.set(4, 5);
        REQUIRE(a[0] == 4);
        REQUIRE(a[1] == 5);

        a = 7;
        REQUIRE(a[0] == 7);
        REQUIRE(a[1] == 7);

        Vector<Real, 2> b(8);
        REQUIRE(b[0] == 8);
        REQUIRE(b[1] == 8);

        b.set(9);
        REQUIRE(b[0] == 9);
        REQUIRE(b[1] == 9);
    }
    {
        Vector<Real, 3> a = Vector<Real, 3>(1, 2, 3);
        REQUIRE(a[0] == 1);
        REQUIRE(a[1] == 2);
        REQUIRE(a[2] == 3);

        a.set(4, 5, 6);
        REQUIRE(a[0] == 4);
        REQUIRE(a[1] == 5);
        REQUIRE(a[2] == 6);

        a = 7;
        REQUIRE(a[0] == 7);
        REQUIRE(a[1] == 7);
        REQUIRE(a[2] == 7);

        Vector<Real, 3> b(8);
        REQUIRE(b[0] == 8);
        REQUIRE(b[1] == 8);
        REQUIRE(b[2] == 8);

        b.set(9);
        REQUIRE(b[0] == 9);
        REQUIRE(b[1] == 9);
        REQUIRE(b[2] == 9);
    }
    {
        Vector<Real, 4> a = Vector<Real, 4>(1, 2, 3, 4);
        REQUIRE(a[0] == 1);
        REQUIRE(a[1] == 2);
        REQUIRE(a[2] == 3);
        REQUIRE(a[3] == 4);

        a.set(4, 5, 6, 7);
        REQUIRE(a[0] == 4);
        REQUIRE(a[1] == 5);
        REQUIRE(a[2] == 6);
        REQUIRE(a[3] == 7);

        a = 7;
        REQUIRE(a[0] == 7);
        REQUIRE(a[1] == 7);
        REQUIRE(a[2] == 7);
        REQUIRE(a[3] == 7);

        Vector<Real, 4> b(8);
        REQUIRE(b[0] == 8);
        REQUIRE(b[1] == 8);
        REQUIRE(b[2] == 8);
        REQUIRE(b[3] == 8);

        b.set(9);
        REQUIRE(b[0] == 9);
        REQUIRE(b[1] == 9);
        REQUIRE(b[2] == 9);
        REQUIRE(b[3] == 9);
    }
}

TEST_CASE("VectorSimpleArithmetic (VectorSimpleArithmetic)")
{
    Vector<Real, 3> a = Vector<Real, 3>(1, 2, 3);
    Vector<Real, 3> b = Vector<Real, 3>(4, 5, 6);

    // Vector op Vector

    a += b;
    REQUIRE(a[0] == (Real)1 + 4);
    REQUIRE(a[1] == (Real)2 + 5);
    REQUIRE(a[2] == (Real)3 + 6);

    a.set(1, 2, 3);
    a -= b;
    REQUIRE(a[0] == (Real)1 - 4);
    REQUIRE(a[1] == (Real)2 - 5);
    REQUIRE(a[2] == (Real)3 - 6);

    a.set(1, 2, 3);
    a *= b;
    REQUIRE(a[0] == (Real)1 * 4);
    REQUIRE(a[1] == (Real)2 * 5);
    REQUIRE(a[2] == (Real)3 * 6);

    a.set(1, 2, 3);
    a /= b;
    REQUIRE(a[0] == (Real)1 / 4);
    REQUIRE(a[1] == (Real)2 / 5);
    REQUIRE(a[2] == (Real)3 / 6);

    // Vector op scalar

    a.set(1, 2, 3);
    a += 4;
    REQUIRE(a[0] == (Real)1 + 4);
    REQUIRE(a[1] == (Real)2 + 4);
    REQUIRE(a[2] == (Real)3 + 4);

    a.set(1, 2, 3);
    a -= 4;
    REQUIRE(a[0] == (Real)1 - 4);
    REQUIRE(a[1] == (Real)2 - 4);
    REQUIRE(a[2] == (Real)3 - 4);

    a.set(1, 2, 3);
    a *= 4;
    REQUIRE(a[0] == (Real)1 * 4);
    REQUIRE(a[1] == (Real)2 * 4);
    REQUIRE(a[2] == (Real)3 * 4);

    a.set(1, 2, 3);
    a /= 4;
    REQUIRE(a[0] == (Real)1 / 4);
    REQUIRE(a[1] == (Real)2 / 4);
    REQUIRE(a[2] == (Real)3 / 4);

    a.set(1, 2, 3);
    a = -a;
    REQUIRE(a[0] == (Real)-1);
    REQUIRE(a[1] == (Real)-2);
    REQUIRE(a[2] == (Real)-3);
};

TEST_CASE("VectorArithmetic (VectorArithmetic)")
{
    // Test the expression templates

    Vector<Real, 3> a = Vector<Real, 3>(1, 2, 3);
    Vector<Real, 3> b = Vector<Real, 3>(4, 5, 6);

    Vector<Real, 3> c(a - b);
    REQUIRE(c[0] == -3);
    REQUIRE(c[1] == -3);
    REQUIRE(c[2] == -3);

    c = a * b;
    REQUIRE(c[0] == 4);
    REQUIRE(c[1] == 10);
    REQUIRE(c[2] == 18);

    c = a / b;
    REQUIRE(c[0] == (Real)1/4);
    REQUIRE(c[1] == (Real)2/5);
    REQUIRE(c[2] == (Real)3/6);

    c = a + b;
    REQUIRE(c[0] == 5);
    REQUIRE(c[1] == 7);
    REQUIRE(c[2] == 9);

    c = (a + b) + 5;
    REQUIRE(c[0] == 10);
    REQUIRE(c[1] == 12);
    REQUIRE(c[2] == 14);

    c = 5 + (a + b);
    REQUIRE(c[0] == 10);
    REQUIRE(c[1] == 12);
    REQUIRE(c[2] == 14);

    c = (a + b) * 5;
    REQUIRE(c[0] == 25);
    REQUIRE(c[1] == 35);
    REQUIRE(c[2] == 45);

    c = 5 * (a + b);
    REQUIRE(c[0] == 25);
    REQUIRE(c[1] == 35);
    REQUIRE(c[2] == 45);

    c = -a;
    REQUIRE(c[0] == -1);
    REQUIRE(c[1] == -2);
    REQUIRE(c[2] == -3);
}

TEST_CASE("VectorArray (VectorArray)")
{
    using Real = float;

    Vector<Real, 3> a = Vector<Real, 3>(-1, -2, 3);

    Vector<Real, 3> b;

    b = abs(a);

    REQUIRE(b[0] == abs(a[0]));
    REQUIRE(b[1] == abs(a[1]));
    REQUIRE(b[2] == abs(a[2]));

    a.set(0.25, 0.5, 0.75);

    b = exp(a);

    REQUIRE(b[0] == std::exp(a[0]));
    REQUIRE(b[1] == std::exp(a[1]));
    REQUIRE(b[2] == std::exp(a[2]));

    b = log(a);

    REQUIRE(b[0] == std::log(a[0]));
    REQUIRE(b[1] == std::log(a[1]));
    REQUIRE(b[2] == std::log(a[2]));

    b = pow(a, a);

    REQUIRE(b[0] == std::pow(a[0], a[0]));
    REQUIRE(b[1] == std::pow(a[1], a[1]));
    REQUIRE(b[2] == std::pow(a[2], a[2]));

    b = pow(a, 2);

    REQUIRE(b[0] == std::pow(a[0], (Real)2));
    REQUIRE(b[1] == std::pow(a[1], (Real)2));
    REQUIRE(b[2] == std::pow(a[2], (Real)2));

    b = sqrt(a);

    REQUIRE(b[0] == std::sqrt(a[0]));
    REQUIRE(b[1] == std::sqrt(a[1]));
    REQUIRE(b[2] == std::sqrt(a[2]));

    b = floor(a);

    REQUIRE(b[0] == std::floor(a[0]));
    REQUIRE(b[1] == std::floor(a[1]));
    REQUIRE(b[2] == std::floor(a[2]));

    b = sin(a);

    REQUIRE(b[0] == std::sin(a[0]));
    REQUIRE(b[1] == std::sin(a[1]));
    REQUIRE(b[2] == std::sin(a[2]));

    b = cos(a);

    REQUIRE(b[0] == std::cos(a[0]));
    REQUIRE(b[1] == std::cos(a[1]));
    REQUIRE(b[2] == std::cos(a[2]));

    b = tan(a);

    REQUIRE(b[0] == std::tan(a[0]));
    REQUIRE(b[1] == std::tan(a[1]));
    REQUIRE(b[2] == std::tan(a[2]));

    b = asin(a);

    REQUIRE(b[0] == std::asin(a[0]));
    REQUIRE(b[1] == std::asin(a[1]));
    REQUIRE(b[2] == std::asin(a[2]));

    b = acos(a);

    REQUIRE(b[0] == std::acos(a[0]));
    REQUIRE(b[1] == std::acos(a[1]));
    REQUIRE(b[2] == std::acos(a[2]));

    b = Pastel::atan2(a, a);

    REQUIRE(b[0] == std::atan2(a[0], a[0]));
    REQUIRE(b[1] == std::atan2(a[1], a[1]));
    REQUIRE(b[2] == std::atan2(a[2], a[2]));

    b = inverse(a);

    REQUIRE(b[0] == inverse(a[0]));
    REQUIRE(b[1] == inverse(a[1]));
    REQUIRE(b[2] == inverse(a[2]));
}

namespace
{

    template <integer N>
    void testVectorArithmetic2()
    {
        integer size = (N == Dynamic) ? 100 : N;

        Vector<Real, N> a(ofDimension(size));

        for (integer i = 0;i < size;++i)
        {
            a[i] = i;
        }

        Vector<Real, N> b = a;

        // Vector + Vector.
        {
            Vector<Real, N> c = b + b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i + i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector += Vector.
        {
            Vector<Real, N> c = b;
            c += b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i + i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector - Vector.
        {
            Vector<Real, N> c = b - b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i - i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector -= Vector.
        {
            Vector<Real, N> c = b;
            c -= b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i - i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector * Vector.
        {
            Vector<Real, N> c = b * b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i * i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector *= Vector.
        {
            Vector<Real, N> c = b;
            c *= b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i * i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector / Vector.
        {
            Vector<Real, N> c = b / b;
            integer contentsDiffer = 0;
            for (integer i = 1;i < size;++i)
            {
                if (c[i] != (Real)i / i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector /= Vector.
        {
            Vector<Real, N> c = b;
            c /= b;
            integer contentsDiffer = 0;
            for (integer i = 1;i < size;++i)
            {
                if (c[i] != (Real)i / i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector + Scalar.
        {
            Vector<Real, N> c = b + 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i + 5)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector + Scalar.
        {
            Vector<Real, N> c = b;
            c += 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i + 5)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector - Scalar.
        {
            Vector<Real, N> c = b - 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i - 5)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector -= Scalar.
        {
            Vector<Real, N> c = b;
            c -= 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i - 5)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector * Scalar.
        {
            Vector<Real, N> c = b * 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i * 5)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector *= Scalar.
        {
            Vector<Real, N> c = b;
            c *= 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != i * 5)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector / Scalar.
        {
            Vector<Real, N> c = b / 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                Real five = 5;
                Real invFactor = 1 / five;
                Real left = i;

                if (c[i] != left * invFactor)
                {
                    //std::cout << c[i] << " != " << i * invFactor << std::endl;
                    //std::cout << i << " / " << size << std::endl;

                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Vector /= Scalar.
        {
            Vector<Real, N> c = b;
            c /= 5;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                Real invFactor = (Real)1 / 5;
                Real result = i;

                result *= invFactor;
                if (c[i] != result)
                {
                    std::cout << c[i] << " != " << result << std::endl;
                    //std::cout << c[i] << " != " << i * invFactor << std::endl;
                    std::cout << i << " / " << size << std::endl;

                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Scalar + Vector.
        {
            Vector<Real, N> c = 5 + b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != 5 + i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Scalar - Vector.
        {
            Vector<Real, N> c = 5 - b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != 5 - i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Scalar * Vector.
        {
            Vector<Real, N> c = 5 * b;
            integer contentsDiffer = 0;
            for (integer i = 0;i < size;++i)
            {
                if (c[i] != 5 * i)
                {
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }

        // Scalar / Vector.
        {
            Vector<Real, N> c = 5 / b;
            integer contentsDiffer = 0;
            for (integer i = 1;i < size;++i)
            {
                Real left = 5;
                if (c[i] != left / i)
                {
                    //std::cout << c[i] << " != " << left / i << std::endl;
                    ++contentsDiffer;
                }
            }
            REQUIRE(contentsDiffer == 0);
        }
    }

    template <integer N>
    void testCollaboration()
    {
        integer size = (N == Dynamic) ? 10 : N;

        Vector<Real, N> a(ofDimension(size));

        // Static-sized vectors must be
        // constructible from dynamic-sized vectors
        // and vice versa. Same thing for
        // assignment.
        {
            Vector<Real> a(ofDimension(size));
            Vector<Real, N> b(a);
            Vector<Real> c(b);

            a = b;
            b = a;

            Tuple<Real, N> d(ofDimension(size));
            Tuple<Real> e(d);
            Tuple<Real, N> f(e);
            e = d;
            d = e;
        }

        Vector<Real, N> b = a;

        Vector<Real, N> e = a;
        REQUIRE(e.size() == size);

        Tuple<Real, N> c = b.asTuple();
        REQUIRE(c.size() == size);

        Tuple<Real, N> d = c;
        REQUIRE(c.size() == size);

        d = c;
        REQUIRE(d.size() == size);

        Tuple<Real, N> f = d;
        REQUIRE(f.size() == size);

        {
            // Vectors must be constructible
            // from Tuples.
            Tuple<Real, N> a(ofDimension(size));
            Vector<Real, N> b(a);

            // The N does not need to match.
            Tuple<Real> c(ofDimension(size));
            Vector<Real, N> d(c);
            Tuple<Real> e(asTuple(d));
        }

        // Vector contains a Tuple.
        {
            Vector<Real, N> a(ofDimension(size));
            Tuple<Real, N> b(a.asTuple());
            REQUIRE(b == a.asTuple());
            Tuple<Real, N> c(asTuple(a));
            REQUIRE(c == a.asTuple());
        }
    }

}

TEST_CASE("various (Vector)")
{
    testNullPointerStatic<1>();
    testNullPointerStatic<2>();
    testNullPointerStatic<3>();
    testNullPointerStatic<4>();

    testNullPointer<1>();
    testNullPointer<2>();
    testNullPointer<3>();
    testNullPointer<4>();
    testNullPointer<Dynamic>();

    testVectorArithmetic2<1>();
    testVectorArithmetic2<2>();
    testVectorArithmetic2<3>();
    testVectorArithmetic2<4>();
    testVectorArithmetic2<Dynamic>();

    testCollaboration<1>();
    testCollaboration<2>();
    testCollaboration<3>();
    testCollaboration<4>();
    testCollaboration<Dynamic>();
}