



// LiDIA - a library for computational number theory
//   Copyright (c) 1995 by the LiDIA Group
//
// File        : dense_psr.h 
// Author      : Frank Lehmann (FL), Markus Maurer (MM) 
// Last change : FL/MM, Oct 2 1995, initial version



#ifndef LiDIA_DENSE_POWER_SERIE_H
#define LiDIA_DENSE_POWER_SERIE_H


#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:base_dense_power_serie.h>
#include <LiDIA:sparse_power_serie.h>
#include <LiDIA:bigmod.h>

#else
#include <LiDIA/base_dense_power_serie.h>
#include <LiDIA/sparse_power_serie.h>
#include <LiDIA/bigmod.h>
#endif


 template < class T > class dense_power_serie : public base_dense_power_serie< T >

  {

    protected :

    //
    // ***** protected member functions *****
    //

    void square   (const dense_power_serie< T >& a);
    void multiply (const dense_power_serie< T > & a, const dense_power_serie< T > & b);
    void invert   (const dense_power_serie< T >& a);
    void power    (const dense_power_serie< T >& a, long n);
    void divide   (const dense_power_serie< T >& a, const dense_power_serie< T >& b);
    void divide   (const T & b, const dense_power_serie< T > & a);
    

    public :

    //
    // ***** constructors / destructor *****
    //

    dense_power_serie ();
    dense_power_serie ( const T & a, lidia_size_t l );
    dense_power_serie ( const base_vector< T > & a, lidia_size_t f );
    dense_power_serie ( const base_dense_power_serie< T > & a );
    ~dense_power_serie ();


    //
    // ***** assignment - operator *****
    //
    
    const dense_power_serie< T > & operator= ( const dense_power_serie< T > & a );
    const dense_power_serie< T > & operator= ( const sparse_power_serie< T > & a );


    //
    // ***** arithmetic via functions *****
    //

    inline friend
    void
    square (dense_power_serie< T >& c, const dense_power_serie< T >& a)
     {c.square(a);}

    inline friend 
    void
    multiply (dense_power_serie< T >& c, const dense_power_serie< T > & a, const dense_power_serie< T > & b)
     {c.multiply(a,b);}

    inline friend
    void
    invert (dense_power_serie< T >& c, const dense_power_serie< T >& a)
     {c.invert(a);}

    inline friend
    void
    power (dense_power_serie< T >& c, const dense_power_serie< T >& a, long n)
     {c.power(a,n);}

    inline friend
    void
    divide (dense_power_serie< T >& c, dense_power_serie< T >& a, dense_power_serie< T >& b)
     {c.divide(a,b);}

    inline friend
    void
    divide (dense_power_serie< T >& c, const T & b, const dense_power_serie< T > & a)
     {c.divide(b,a);}


    //
    // ***** arithmetic via operators *****
    //

    inline friend 
    dense_power_serie< T >
    operator*  (const dense_power_serie< T > & a,
		const dense_power_serie< T > & b)
     {dense_power_serie<T> c; c.multiply(a,b); return c;}

    inline friend
    const dense_power_serie< T > &
    operator*= (dense_power_serie< T > & a,
		const dense_power_serie< T > & b)
     {a.multiply(a,b); return a;}

    inline friend
    dense_power_serie< T > 
    operator/ (const dense_power_serie< T > & a,
	       const dense_power_serie< T > & b)
     {dense_power_serie<T> c; c.divide(a,b); return c;}

    inline friend
    dense_power_serie< T >
    operator/ (const T & b,
	       const dense_power_serie< T > & a)
     {dense_power_serie<T> c; c.divide(b,a); return c;}

    inline friend 
    const dense_power_serie< T > &
    operator/= (dense_power_serie< T > & a,
		const dense_power_serie< T > & b)
     {a.divide(a,b); return a;}
  } ;




#ifndef NO_PSR_BIGMOD


 /******************************************************************************/
 /*************** Specialization : dense_power_serie<bigmod> *******************/
 /******************************************************************************/


 class dense_power_serie< bigmod > : public base_dense_power_serie< bigmod >

  {

    protected :

    //
    // ***** protected member functions *****
    //

    void square   (const dense_power_serie< bigmod >& a);
    void multiply (const dense_power_serie< bigmod > & a, const dense_power_serie< bigmod > & b);
    void invert   (const dense_power_serie< bigmod >& a);
    void power    (const dense_power_serie< bigmod >& a, long n);
    void divide   (const dense_power_serie< bigmod >& a, const dense_power_serie< bigmod >& b);
    void divide   (const bigmod & b, const dense_power_serie< bigmod > & a);
    

    public :

    //
    // ***** constructors / destructor *****
    //

    dense_power_serie ();
    dense_power_serie ( const bigmod & a, lidia_size_t l );
    dense_power_serie ( const base_vector< bigmod > & a, lidia_size_t f );
    dense_power_serie ( const base_dense_power_serie< bigmod > & a );
   ~dense_power_serie (){}


    //
    // ***** assignment - operator *****
    //
    
    const dense_power_serie< bigmod > & operator= ( const dense_power_serie< bigmod > & a );
    const dense_power_serie< bigmod > & operator= ( const sparse_power_serie< bigmod > & a );


    //
    // ***** arithmetic via functions *****
    //

    inline friend
    void
    square (dense_power_serie< bigmod >& c, const dense_power_serie< bigmod >& a)
     {c.square(a);}

    inline friend 
    void
    multiply (dense_power_serie< bigmod >& c, const dense_power_serie< bigmod > & a, const dense_power_serie< bigmod > & b)
     {c.multiply(a,b);}

    inline friend
    void
    invert (dense_power_serie< bigmod >& c, const dense_power_serie< bigmod >& a)
     {c.invert(a);}

    inline friend
    void
    power (dense_power_serie< bigmod >& c, const dense_power_serie< bigmod >& a, long n)
     {c.power(a,n);}

    inline friend
    void
    divide (dense_power_serie< bigmod >& c, dense_power_serie< bigmod >& a, dense_power_serie< bigmod >& b)
     {c.divide(a,b);}

    inline friend
    void
    divide (dense_power_serie< bigmod >& c, const bigmod & b, const dense_power_serie< bigmod > & a)
     {c.divide(b,a);}


    //
    // ***** arithmetic via operators *****
    //

    inline friend 
    dense_power_serie< bigmod >
    operator* (const dense_power_serie< bigmod > & a,
               const dense_power_serie< bigmod > & b)
     {dense_power_serie<bigmod> c; c.multiply(a,b); return c;}

    inline friend
    const dense_power_serie< bigmod > &
    operator*= (dense_power_serie< bigmod > & a,
                const dense_power_serie< bigmod > & b)
     {a.multiply(a,b); return a;}

    inline friend
    dense_power_serie< bigmod > 
    operator/ (const dense_power_serie< bigmod > & a,
               const dense_power_serie< bigmod > & b)
     {dense_power_serie<bigmod> c; c.divide(a,b); return c;}

    inline friend
    dense_power_serie< bigmod >
    operator/ (const bigmod & b,
               const dense_power_serie< bigmod > & a)
     {dense_power_serie<bigmod> c; c.divide(b,a); return c;}

    inline friend 
    const dense_power_serie< bigmod > &
    operator/= (dense_power_serie< bigmod > & a,
                const dense_power_serie< bigmod > & b)
     {a.divide(a,b); return a;}

  } ;

#endif


#ifdef LIDIA_INCLUDE_C
#include <LiDIA/dense_power_serie.c>
#endif

#endif






