コード例 #1
0
ファイル: checkmatrices.cpp プロジェクト: zettoone/cpp-warmup
void math(ErrorContext &ec, int level)
{
    ec.DESC("--- Arithmetic operators ---");

    // Note that these tests depend heavily on previously tested operations!
    // They should not be run unless everything else checks out OK.

    if (!ec.ok())
    {
        ec.DESC("one or more previous failures; skipping this section");
        ec.result(false);
        return;
    }

    for (int pass = 1; pass <= level / 2; pass++)
    {
        // Make up some dimensions for these matrices.
        const int x = (pass > 1) ? (rnd(level) + 1) : 0;
        const int y = (pass > 1) ? (rnd(level) + 1) : 0;
        const int z = (pass > 1) ? (rnd(level) + 1) : 0;

        // These will be three random matrices.
        Matrix a(x, y);
        Matrix b(x, y);
        Matrix c(y, z);

        // These will be the correct results of arithmetic operations.
        Matrix a_plus_b(x, y);
        Matrix a_minus_b(x, y);
        Matrix a_times_c(x, z);

        // Fill in the values and results.

        for (int ix = 0; ix < x; ix++)
        {
            for (int iy = 0; iy < y; iy++)
            {
                const int va = rnd();
                const int vb = rnd();

                a.setelem(ix, iy, va);
                b.setelem(ix, iy, vb);

                a_plus_b.setelem(ix, iy, va + vb);
                a_minus_b.setelem(ix, iy, va - vb);
            }
        }

        for (int iy = 0; iy < y; iy++)
        {
            for (int iz = 0; iz < z; iz++)
            {
                const int vc = rnd();
                c.setelem(iy, iz, vc);

                for (int ix = 0; ix < x; ix++)
                {
                    a_times_c.setelem(ix, iz, a_times_c.getelem(ix, iz)
                                      + vc * a.getelem(ix, iy));
                }
            }
        }

        // Set up read-only copies of the three reference matrices.
        const Matrix copy_a = a;
        const Matrix copy_b = b;
        const Matrix copy_c = c;

        // Check non-destructive addition.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") + (" << x << " by "
                << y << ")" << ", return value" << ends;
            ec.DESC(oss.str());
            ec.result(copy_a + copy_b == a_plus_b);
        }

        // Ensure arguments were not altered.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") + (" << x << " by "
                << y << ")" << ", side effects" << ends;
            ec.DESC(oss.str());
            ec.result(copy_a == a && copy_b == b);
        }

        // Check non-destructive subtraction.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") - (" << x << " by "
                << y << ")" << ", return value" << ends;
            ec.DESC(oss.str());
            ec.result(copy_a - copy_b == a_minus_b);
        }

        // Ensure arguments were not altered.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") - (" << x << " by "
                << y << ")" << ", side effects" << ends;
            ec.DESC(oss.str());
            ec.result(copy_a == a && copy_b == b);
        }

        // Check non-destructive multiplication.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") * (" << y << " by "
                << z << ")" << ", return value" << ends;
            ec.DESC(oss.str());
            ec.result(copy_a * copy_c == a_times_c);
        }

        // Ensure arguments were not altered.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") * (" << y << " by "
                << z << ")" << ", side effects" << ends;
            ec.DESC(oss.str());
            ec.result(copy_a == a && copy_c == c);
        }

        // Check destructive addition.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") += (" << x << " by "
                << y << ")" << ", return value" << ends;
            ec.DESC(oss.str());
            ec.result((a_minus_b += copy_b) == copy_a);
        }

        // Ensure LHS was altered and RHS was not.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") += (" << x << " by "
                << y << ")" << ", side effects" << ends;
            ec.DESC(oss.str());
            ec.result(a_minus_b == copy_a && copy_b == b);
        }

        // Check destructive subtraction.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") -= (" << x << " by "
                << y << ")" << ", return value" << ends;
            ec.DESC(oss.str());
            ec.result((a_plus_b -= b) == copy_a);
        }

        // Ensure LHS was altered and RHS was not.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") -= (" << x << " by "
                << y << ")" << ", side effects" << ends;
            ec.DESC(oss.str());
            ec.result(a_plus_b == copy_a && copy_b == b);
        }

        // Check destructive multiplication.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") *= (" << y << " by "
                << z << ")" << ", return value" << ends;
            ec.DESC(oss.str());
            ec.result((a *= copy_c) == a_times_c);
        }

        // Ensure LHS was altered and RHS was not.
        {
            ostringstream oss;
            oss << "(" << x << " by " << y << ") *= (" << y << " by "
                << z << ")" << ", side effects" << ends;
            ec.DESC(oss.str());
            ec.result(a == a_times_c && copy_c == c);
        }
    }
}