



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




#ifndef LIDIA_SPARSE_POWER_SERIE_H
#define LIDIA_SPARSE_POWER_SERIE_H


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

#else
#include <LiDIA/base_sparse_power_serie.h>
#include <LiDIA/bigmod.h>
#endif



  // **************************************************************************
  // *
  // *    class name :  sparse_power_serie< T >
  // *
  // **************************************************************************



  template <class T> class sparse_power_serie : public base_sparse_power_serie<T>
   {

    protected :

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

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


    public :

      //
      // ****  constructor/destructor functions    ******
      //

      sparse_power_serie ();
      sparse_power_serie ( const T & a, lidia_size_t l );
      sparse_power_serie ( const base_vector<T> & a, lidia_size_t f );
      sparse_power_serie ( const base_sparse_power_serie< T > & x );
      ~sparse_power_serie ();


      //
      //  *****  assignment operator  ***** 
      //

      const sparse_power_serie< T > & operator = ( const base_sparse_power_serie< T > & x );


      //
      // ***** arithmetical procedures *****
      //

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

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

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

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

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



      //
      //  *****  arithmetical operators  *****
      //

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

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

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

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

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

   } ;




#ifndef NO_PSR_BIGMOD

   /******************************************************************************/
   /*************** Specialization : sparse_power_serie<bigmod> ******************/
   /******************************************************************************/


  class sparse_power_serie<bigmod> : public base_sparse_power_serie<bigmod>
   {

    protected :

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

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


    public :

      //
      // ****  constructor/destructor functions    ******
      //

      sparse_power_serie ();
      sparse_power_serie ( const bigmod & a, lidia_size_t l );
      sparse_power_serie ( const base_vector<bigmod> & a, lidia_size_t f );
      sparse_power_serie ( const base_sparse_power_serie< bigmod > & x );
    ~sparse_power_serie (){};


      //
      //  *****  assignment operator  ***** 
      //

      const sparse_power_serie< bigmod > & operator = ( const base_sparse_power_serie< bigmod > & x );


      //
      // ***** arithmetical procedures *****
      //

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

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

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

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

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



      //
      //  *****  arithmetical operators  *****
      //

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

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

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

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

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

   } ;

#endif

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

#endif


