//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//



#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)

#include <LiDIA:single_factor.h>
#include <LiDIA:factorization.h>

#else
  
#include <LiDIA/single_factor.h>
#include <LiDIA/factorization.h>
  
#endif



/*********************************************************************
				class single_factor< T >
*********************************************************************/

template< class T >
single_factor< T >::single_factor() : base_factor< T >()
{
    //DEFAULT VALUE MUST BE '1', i.e. the neutral element of multiplication !!!
    rep = 1;   //rep.assign_one();
}


template< class T >
single_factor< T >::single_factor(const single_factor< T > & x) : base_factor< T >(x)
{ }


template< class T >
single_factor< T >::single_factor(const T & x)
{
    rep = x;
    set_prime_flag(unknown);
}


template< class T >
single_factor< T >::~single_factor()
{ }


template< class T >
single_factor< T > & 
single_factor< T >::operator= (const single_factor< T > & x)
{
    assign(x);
    return *this;
}


template< class T >
const T &
single_factor< T >::operator= (const T & x)
{
    assign(x);
    return x;
}


template< class T >
void
single_factor< T >::assign(const single_factor< T > & x)
{
    rep = x.rep;
    set_prime_flag(x.prime_flag());
}


template< class T >
void
single_factor< T >::assign(const T & x)
{
    rep = x;
    set_prime_flag(unknown);
}


template< class T >
T single_factor< T >::extract_unit()
{
//DEFAULT VARIANT: always returns '1' and leaves rep unchanged

    single_factor< T > one;
    return one.rep;
}

template< class T >
lidia_size_t ord_divide(const single_factor< T > &a, single_factor< T > &b)
{
    if (a.is_one())
	lidia_error_handler("single_factor<T>","ord_divide::1st argument mustn't be 1");
	
    single_factor< T > tmp;
    lidia_size_t e = 0;
    gcd(tmp, a, b);
    while (tmp == a)
    {
	e++;
	divide(b, b, a);
	gcd(tmp, a, b);
    }
    return e;
}

template< class T >
factorization< T > single_factor< T >::factor() const
  //standard factorization algorithm, 
  //called by factorization<T>::factor_all_components(), here: dummy version
{
    lidia_error_handler( "single_factor< T >", "factor( void )::not implemented" );
    factorization< T > F;
    F.assign(*this);
    return F;
}


template< class T >
bool single_factor< T >::is_one() const
{
    single_factor< T > ONE;		/* default value is '1' */
    return (*this == ONE);
}

template< class T > 
bool single_factor< T >::is_prime_factor(int test)
{
    if (prime_flag() == prime)
	return true;
  
    if (test == 0)		//=> no explicit primality test
	return false;


// NO DEFAULT PRIMALITY TEST

    lidia_error_handler( "factorization< T >", "is_prime_factor( int )::explicit test not implemented" );
    return false;
}


template< class T >
factorization< T > factor(const single_factor< T > & f)
{
    return f.factor();
}
