Revision 0af6ee1f25b27faea2a7b566647c8aa9b5820327 authored by Clement Pernet on 31 May 2017, 12:01:20 UTC, committed by Clement Pernet on 31 May 2017, 12:01:20 UTC
2 parent s bda32bb + e873aaf
Raw File
test-charpoly.C
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by Clément Pernet
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */

//--------------------------------------------------------------------------
//                        Test for charpoly
//
//--------------------------------------------------------------------------
// Clement Pernet
//-------------------------------------------------------------------------

//#define ENABLE_ALL_CHECKINGS


#include <iostream>
#include <iomanip>
#include "givaro/modular.h"
#include "fflas-ffpack/utils/fflas_io.h"
#include "fflas-ffpack/utils/fflas_randommatrix.h"
#include "fflas-ffpack/ffpack/ffpack.h"

#include "fflas-ffpack/utils/args-parser.h"
#include "test-utils.h"


using namespace std;

using namespace FFPACK;

template<class Field, class RandIter>
bool launch_test(const Field & F, size_t n, typename Field::Element * A, size_t lda,
				 size_t nbit, RandIter& G, FFPACK::FFPACK_CHARPOLY_TAG CT)
{
	std::ostringstream oss;
	switch (CT){
	    case FfpackAuto: oss<<"Automated variant choice"; break;
	    case FfpackLUK: oss<<"LUKrylov variant"; break;
	    case FfpackKG: oss<<"Keller-Gehrig variant"; break;
	    case FfpackDanilevski: oss<<"Danilevskii variant"; break;
	    case FfpackKGFast:  oss<<"KGFast variant"; break;
	    case FfpackKGFastG: oss<<"KGFastG variant"; break;
	    case FfpackHybrid: oss<<"Hybrid variant"; break;
	    case FfpackArithProg: oss<<"ArithProg variant"; break;
	    default: oss<<"LUKrylov variant"; break;
	}
	F.write(oss<<" over ");
	std::cout.fill('.');
	std::cout<<"Checking ";
	std::cout.width(70);
	std::cout<<oss.str();
	std::cout<<"...";

	typedef typename Givaro::Poly1Dom<Field> PolRing;
	typedef typename PolRing::Element Polynomial;
	Polynomial charp(n+1);

	typename Field::Element_ptr B = FFLAS::fflas_new(F, n,n);
	FFLAS::fassign(F, n, n, A, lda, B, n);

	Checker_charpoly<Field,Polynomial> checker(F,n,A,lda);

	PolRing R(F);
  
	FFPACK::CharPoly (R, charp, n, A, lda, G, CT);

	 try{
	 	checker.check(charp);
	 }
	 catch (FailureCharpolyCheck){
	 	std::cerr<<"CharPoly Checker FAILED"<<std::endl;
	 	FFLAS::fflas_delete (B);
	 	return false;
	 }

	FFLAS::fassign(F, n, n, B, n, A, lda);

		// Checking trace(A) == charp[n-1]
	typename Field::Element trace;
	F.init(trace, F.zero);
	for (size_t i = 0; i < n; i++)
		F.subin (trace, B [i*(n+1)]);
	if (!F.areEqual(trace, charp[n-1])){
		std::cerr<<"FAILED: trace = "<<trace<<" P["<<n-1<<"] = "<<charp[n-1]<<std::endl;
		FFLAS::fflas_delete (B);
		return false;
	}

		// Checking det(A) == charp[0]
	typename Field::Element det;
	F.init(det);
	F.assign(det, FFPACK::Det(F, n, n, B, n));
	FFLAS::fflas_delete (B);

	if (n&1) F.negin(det); // p0 == (-1)^n det
	
	if (!F.areEqual(det,charp[0])){
		std::cerr<<"FAILED: det = "<<det<<" P["<<0<<"] = "<<charp[0]<<std::endl;
		return false;
	}

	std::cout<<"PASSED"<<std::endl;
	return true ;
}

template<class Field>
bool run_with_field(const Givaro::Integer p, uint64_t bits, size_t n, std::string file, int variant, size_t iter, size_t seed){
	FFPACK::FFPACK_CHARPOLY_TAG CT;
	switch (variant){
	    case 0: CT = FfpackAuto; break;
	    case 1: CT = FfpackDanilevski; break;
	    case 2: CT = FfpackLUK; break;
	    case 3: CT = FfpackArithProg; break;
	    case 4: CT = FfpackKG; break;
	    case 5: CT = FfpackKGFast; break;
	    case 6: CT = FfpackHybrid; break;
	    case 7: CT = FfpackKGFastG; break;
	    default: CT = FfpackAuto; break;
	}

	bool passed = true;
	size_t lda = n;

	for (size_t i=0;i<iter;i++){
		Field* F= chooseField<Field>(p,bits);
		if (F==nullptr){
			return true;
		}
		typename Field::RandIter R(*F,bits,seed);

		typename Field::Element * A=NULL;

		if (!file.empty()) {
			/* user provided test matrix */
			//const char * filestring = file.c_str();
			FFLAS::ReadMatrix(file,*F,n,n,A);
		} else {
				/* Random matrix test */
			A = FFLAS::fflas_new(*F,n,lda);
			A = FFPACK::RandomMatrix(*F,n,n,A,lda,R);
		}

		if (variant) // User provided variant
			passed &= launch_test<Field>(*F, n, A, lda, iter, R, CT);
		else{ // No variant specified, testing them all
			passed &= launch_test<Field>(*F, n, A, lda, iter, R, FfpackDanilevski);
			passed &= launch_test<Field>(*F, n, A, lda, iter, R, FfpackLUK);
			passed &= launch_test<Field>(*F, n, A, lda, iter, R, FfpackArithProg);
			passed &= launch_test<Field>(*F, n, A, lda, iter, R, FfpackAuto);
				//passed &= launch_test<Field>(F, n, A, lda, iter, FfpackKG); // fails (variant only implemented for benchmarking
				//passed &= launch_test<Field>(*F, n, A, lda, iter, FfpackKGFast); // generic: does not work with any matrix
				//passed &= launch_test<Field>(*F, n, A, lda, iter, FfpackKGFastG); // generic: does not work with any matrix
				//passed &= launch_test<Field>(*F, n, A, lda, iter, FfpackHybrid); // fails with small characteristic
		}
		FFLAS::fflas_delete (A);
		delete F;
	}
	return passed;
}

int main(int argc, char** argv)
{
	Givaro::Integer q = -1; // characteristic
	uint64_t     bits = 0;       // bit size
	size_t       iter = 3; // repetitions
	size_t       n = 300;
	std::string  file = "" ; // file where
	bool loop = false; // loop infintely
	std::string  mat_file = "" ; // input matrix file 
	int variant = 0; // default value 0: test all variants
	size_t seed =  time(NULL);

	std::cout<<setprecision(17);
	srand((int)time(NULL));

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic.", TYPE_INTEGER , &q },
		{ 'b', "-b B", "Set the bitsize of the random elements.",         TYPE_INT , &bits},
		{ 'n', "-n N", "Set the size of the matrix.", TYPE_INT , &n },
		{ 'i', "-i I", "Set number of repetitions.", TYPE_INT , &iter },
		{ 'f', "-f file", "Set input file", TYPE_STR, &mat_file },
		{ 'a', "-a algorithm", "Set the algorithm variant", TYPE_INT, &variant },
		{ 'l', "-l Y/N", "run the test in an infinte loop.", TYPE_BOOL , &loop },
		{ 's', "-s seed", "Set seed for the random generator", TYPE_INT, &seed },
		END_OF_ARGUMENTS
	};
	FFLAS::parseArguments(argc,argv,as);

	bool passed = true;
	do {
		passed &= run_with_field<Givaro::ModularBalanced<float> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::Modular<float> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::ModularBalanced<double> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::Modular<double> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::ModularBalanced<int32_t> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::Modular<int32_t> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::ModularBalanced<int64_t> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::Modular<int64_t> >(q, bits, n, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::Modular<Givaro::Integer> >(q, 6, n/2, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::Modular<Givaro::Integer> >(q, (bits?bits:512), n/4, mat_file, variant, iter, seed);
		passed &= run_with_field<Givaro::ZRing<Givaro::Integer> >(q, (bits?bits:80_ui64), n/4, mat_file, variant, iter, seed);

		// if ((i+1)*100 % nbit == 0)
		// 	std::cerr<<double(i+1)/nbit*100<<" % "<<std::endl;
	} while (loop && passed);
	return !passed;
}
back to top