


// 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
//		 FL/MM, Oct 2 1995, removed the randomize-function to allow
//				    power series over Q, R and C.




#ifndef LIDIA_BASE_SPARSE_POWER_SERIE_H
#define LIDIA_BASE_SPARSE_POWER_SERIE_H


#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:lidia.h>
#include <LiDIA:sort_vector.h>
#include <LiDIA:coeff_sparse_power_serie.h>

#else
#include <LiDIA/lidia.h>
#include <LiDIA/sort_vector.h>
#include <LiDIA/coeff_sparse_power_serie.h>
#endif


/*
// only used in randomize()
#include <LiDIA/bigint.h>
*/



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



template <class T> class base_sparse_power_serie

 {

  protected :
    
    lidia_size_t first ;
    lidia_size_t last  ;
    sort_vector< spc< T > >  *coeff ;  
    bool sorted ;
    char *errmess ;


    //
    //  *****  some protected member functions  *****
    //
    
    inline lidia_size_t alloc_size ( lidia_size_t sz )
     {return sz;}

    inline void sort ( void ) 
     {coeff->sort(); sorted = true;}

    inline void sort_test ( void ) const
      {	if ( sorted == false ) 
	  lidia_error_handler ( "base_sparse_power_serie< T >" , "invalid structure: please, use sort()" ) ;
      }

    void init_test ( char * mess ) const;
    void rebuild (void );


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

    void add ( const base_sparse_power_serie< T > & a, const base_sparse_power_serie< T > & b );
    void add ( const base_sparse_power_serie< T > & a, const T & b );
    void add ( const T & b, const base_sparse_power_serie< T > & a );

    void subtract ( const base_sparse_power_serie< T > & a, const base_sparse_power_serie< T > & b );
    void subtract ( const base_sparse_power_serie< T > & a, const T & b );
    void subtract ( const T & b, const base_sparse_power_serie< T > & a );

    void multiply ( const base_sparse_power_serie< T > & a, const T & b );
    void multiply ( const T & b, const base_sparse_power_serie< T > & a );

    void divide ( const base_sparse_power_serie< T > & a, const T & b );
    void negate ( const base_sparse_power_serie< T > & a );

    void swap ( base_sparse_power_serie< T > & b );



  public :

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

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


    //
    //  *****  initialization functions  *****
    //

    bool is_one  ( void ) const;
    bool is_zero ( void ) const;
    void assign_zero ( lidia_size_t l );
    void assign_one ( lidia_size_t l );

    void set ( const T & elem , lidia_size_t l );
    void set ( const T * c, const lidia_size_t * e, lidia_size_t sz, lidia_size_t l );
    // void set ( const base_vector< T > & c, const base_vector< lidia_size_t > & e , lidia_size_t l );
    void set_coeff ( const T & elem , lidia_size_t exp );
    void reduce_last ( lidia_size_t l );
    void clear ( void );
    void normalize ( void );


    //
    //  *****  information functions  *****
    //

    lidia_size_t get_first ( void ) const;
    lidia_size_t get_last ( void ) const;

    void get ( T * & c, lidia_size_t * & e, lidia_size_t & sz ) const;
    // void get ( base_vector< T > & c , base_vector< lidia_size_t > & e ) const;
    void get_coeff ( T & elem , lidia_size_t exp ) const;


    //
    //  *****  subscription operator  *****
    //

    T operator [] ( lidia_size_t exp ) const;


    //
    //  *****  I/O functions and operators  *****
    //

    int read ( istream & in );
    int write ( ostream & out ) const;
    void info ( ostream & out ) const;

    inline friend
    istream &
    operator >> ( istream & in , base_sparse_power_serie< T > & a )
      {a.read(in); return (in);}

    inline friend
    ostream &
    operator << ( ostream & out , const base_sparse_power_serie< T > & a )
      {a.write(out); return (out);}
  

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

    const base_sparse_power_serie< T > & operator = ( const base_sparse_power_serie< T > & a );


    //
    //  ***** swap - function *****
    //

    inline friend 
    void
    swap ( base_sparse_power_serie< T > & a , base_sparse_power_serie< T > & b )
     {a.swap(b);}



    //
    //  *****  comparison of series *****
    //

    bool operator == ( const base_sparse_power_serie< T > & b ) const;
    bool operator != ( const base_sparse_power_serie< T > & b ) const;


    //
    //  *****  generating random series  *****
    //

    // friend
    // void
    // randomize ( base_sparse_power_serie< T > & a , lidia_size_t f, lidia_size_t l , lidia_size_t all , const T & max );



    //
    //  *****  arithmetical operations  *****
    //

    void multiply_by_xn ( lidia_size_t n );
    void compose ( lidia_size_t n );

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

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

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



    //
    //  *****  scalar - operations  *****
    //


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

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

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

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

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

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


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

    //  -----  addition  -----

    inline friend 
    base_sparse_power_serie< T > 
    operator + ( const base_sparse_power_serie< T > & a,
		 const base_sparse_power_serie< T > & b ) 
      {base_sparse_power_serie< T > res; res.add(a,b); return res;}

    inline friend 
    base_sparse_power_serie< T > 
    operator + ( const base_sparse_power_serie< T > & a,
		 const T & b ) 
      {base_sparse_power_serie< T > res; res.add(a,b);return res;}

    inline friend 
    base_sparse_power_serie< T > 
    operator + ( const T & a,
		 const base_sparse_power_serie< T > & b ) 
      {base_sparse_power_serie< T > res; res.add(a,b); return res;}

    inline friend
    const base_sparse_power_serie< T > & 
    operator += ( base_sparse_power_serie< T > & a,
		  const base_sparse_power_serie< T > & b ) 
      {a.add(a,b); return a;}

    inline friend
    const base_sparse_power_serie< T > & 
    operator += ( base_sparse_power_serie< T > & a,
		  const T & b ) 
      {a.add(a,b); return a;}



    //  -----  subtraction  -----

    inline friend 
    base_sparse_power_serie< T > 
    operator - ( const base_sparse_power_serie< T > & a ) 
      {base_sparse_power_serie< T > res; res.negate (a); return res;}

    inline friend 
    base_sparse_power_serie< T > 
    operator - ( const base_sparse_power_serie< T > & a,
		 const base_sparse_power_serie< T > & b ) 
      {base_sparse_power_serie< T > res; res.subtract (a,b); return res;}

    inline friend 
    base_sparse_power_serie< T > 
    operator - ( const base_sparse_power_serie< T > & a,
		 const T & b ) 
      {base_sparse_power_serie< T > res; res.subtract(a,b); return res;}

    inline friend 
    base_sparse_power_serie< T > 
    operator - ( const T & a,
		 const base_sparse_power_serie< T > & b ) 
      {base_sparse_power_serie< T > res; res.subtract(a,b); return res;}

    inline friend
    const base_sparse_power_serie< T > & 
    operator -= ( base_sparse_power_serie< T > & a,
		  const base_sparse_power_serie< T > & b ) 
      {a.subtract(a,b); return a;}

    inline friend
    const base_sparse_power_serie< T > & 
    operator -= ( base_sparse_power_serie< T > & a,
		  const T & b ) 
      {a.subtract(a,b);	return a;}



    //  -----  multiplication  -----

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

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

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



    //  -----  division  -----

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

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


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

#endif 

