bool testMul (Context<Ring, Modules> &ctx, const Matrix1 &A, const Matrix2 &B, const Matrix3 &C)
{
	commentator.start ("Testing StrassenWinograd::gemm (b = 0)", __FUNCTION__);

	std::ostream &report = commentator.report (Commentator::LEVEL_NORMAL, INTERNAL_DESCRIPTION);
	std::ostream &reportUI = commentator.report (Commentator::LEVEL_UNIMPORTANT, INTERNAL_DESCRIPTION);
	std::ostream &error = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR);

	bool pass = true;

	typename Matrix3::ContainerType Cp1 (C.rowdim (), C.coldim ()), Cp2 (C.rowdim (), C.coldim ());

	BLAS3::scal (ctx, ctx.F.zero (), Cp1);
	BLAS3::scal (ctx, ctx.F.zero (), Cp2);

	reportUI << "A = " << std::endl;
	BLAS3::write (ctx, reportUI, A);

	reportUI << "B = " << std::endl;
	BLAS3::write (ctx, reportUI, B);

	typename Ring::Element a;
	NonzeroRandIter<Ring> nri (ctx.F, typename Ring::RandIter (ctx.F));
	nri.random (a);

	report << "Coefficient a = ";
	ctx.F.write (report, a) << std::endl;

	StrassenWinograd<typename GenericModule<Ring>::Tag> sw (1);

	commentator.start ("Strassen-Winograd multiplication");

	sw.gemm (ctx.F, ctx.M, a, A, B, ctx.F.zero (), Cp1);

	commentator.stop (MSG_DONE);

	reportUI << "(From Strassen-Winograd) a * A * B = " << std::endl;
	BLAS3::write (ctx, reportUI, Cp1);

	commentator.start ("Classical multiplication");

	BLAS3::gemm (ctx, a, A, B, ctx.F.zero (), Cp2);

	commentator.stop (MSG_DONE);

	reportUI << "(From classical method) a * A * B = " << std::endl;
	BLAS3::write (ctx, reportUI, Cp2);

	if (!BLAS3::equal (ctx, Cp1, Cp2)) {
		error << "ERROR: Results differ" << std::endl;
		pass = false;
	}

	commentator.stop (MSG_STATUS (pass));

	return pass;
}
bool testgemmcblasConsistency  (LELA::Context<Ring, Modules1> &ctx1,
				LELA::Context<Ring, Modules2> &ctx2,
				const char *text,
				const typename Ring::Element &a, const typename Ring::Element &b,
				const Matrix1 &A1, const Matrix2 &A2,
				const Matrix3 &A3, const Matrix4 &A4,
				const Matrix5 &A5, const Matrix6 &A6)
{

        ostringstream str;
        str << "Testing " << text << " gemm consistency" << std::ends;
        commentator.start (str.str ().c_str ());

	std::ostream &report = commentator.report (Commentator::LEVEL_NORMAL, INTERNAL_DESCRIPTION);

        bool pass = true;

        typename Matrix4::ContainerType A7 (A1.rowdim (), A1.coldim ());
	typename Matrix5::ContainerType A8 (A2.rowdim (), A2.coldim ());

	BLAS3::copy(ctx1, A1, A7);
	BLAS3::copy(ctx1, A2, A8);

        typename Matrix3::ContainerType A9 (A3.rowdim (), A3.coldim ());
	typename Matrix6::ContainerType A10 (A3.rowdim (), A3.coldim ());

	BLAS3::copy(ctx1, A3, A9);
	BLAS3::copy(ctx1, A3, A10);

        report << "Matrix A_1: "<< std::endl;
	BLAS3::write (ctx1, report, A1);

        report << "Matrix A_2: "<< std::endl;
	BLAS3::write (ctx1, report, A2);

	report << "Coefficient b: ";
	ctx1.F.write (report, b) << std::endl;

	report << "Matrix A_3: "<< std::endl;
	BLAS3::write (ctx1, report, A9);

	BLAS3::gemm (ctx1, ctx1.F.one (), A1, A2, b, A9);

        report << "Matrix a A_1 A_2 + b A_3: " << std::endl;
	BLAS3::write (ctx1, report, A9);

        report << "Matrix A_4: "<< std::endl;
	BLAS3::write (ctx1, report, A7);

        report << "Matrix A_5: "<< std::endl;
	BLAS3::write (ctx1, report, A8);

        report << "Matrix A_6: "<< std::endl;
	BLAS3::write (ctx1, report, A10);

	BLAS3::gemm (ctx2, ctx2.F.one (), A7, A8, b, A10);

        report << "Matrix a A_4 A_5 + b A_6: " << std::endl;
	BLAS3::write (ctx2, report, A10);

        if (!BLAS3::equal (ctx1, A9, A10))
		{
			commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
				<< "ERROR: a A_1 A_2 + b A_3  !=  a A_4 A_5 + b A_6 " << std::endl;
			pass = false;
		}

        commentator.stop (MSG_STATUS (pass));

        return pass;
}