//
// LiDIA - a library for computational number theory
//   Copyright (c) 1996 by the LiDIA Group
//
// File        : gf_p_base.h
// Author      : Detlef Anton (DA), Thomas Pfahler (TPf)
// Last change : DA, Jan 10 1996, initial version
//               TPf, Jul 1 1996, added reference counting, min. changes
//

#ifndef LIDIA_GF_P_BASE__H
#define LIDIA_GF_P_BASE__H

#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:galois_field.h>
#include <LiDIA:poly_modulus.h>
#include <LiDIA:gf_p_element.h>
#else
#include <LiDIA/galois_field.h>
#include <LiDIA/poly_modulus.h>
#include <LiDIA/gf_p_element.h>
#endif



class gf_p_base
{
  /**
  ** the C++ type we use to represent a Polynomial Base of a Galois field
  **/

  friend class field_ref;
  
  
  const galois_field *         gf_ptr;
  poly_modulus                 pol_mod;
  LIDIA_MUTABLE lidia_size_t   ref_counter;

  void inc_ref_counter() const;
  void dec_ref_counter() const;

  friend class gf_p_element;
  friend void multiply (gf_p_element & c, const gf_p_element & a, const gf_p_element & b);
  friend void square   (gf_p_element & a, const gf_p_element & b);


  public:

  /**
  ** constructors and destructor
  **/

  gf_p_base();
  gf_p_base(const galois_field & K);
  gf_p_base(const galois_field & K, const Fp_polynomial & pol);
  gf_p_base(const gf_p_base & PB);
  ~gf_p_base();

  /**
  ** access functions
  **/

  const galois_field &   field()      const;
  const Fp_polynomial &  irred_polynomial() const;

  /**
  ** assignments
  **/

  const gf_p_base & operator = (const gf_p_base & PB);
  void assign(const gf_p_base & PB);

  /**
  ** high level functions
  **/

  gf_p_element gen_primitive_elem()      const;
  gf_p_element gen_free_elem()           const;
  gf_p_element gen_free_primitive_elem() const;

  /**
  ** input / output
  **/

  friend istream & operator >> (istream & in, gf_p_base & PB);
  friend ostream & operator << (ostream & out, const gf_p_base & PB);

};

#endif


