//
// LiDIA - a library for computational number theory
//   Copyright (c) 1996 by the LiDIA Group
//
// File        : galois_field.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__H
#define LIDIA_GF__H

#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:bigint.h>
#include <LiDIA:rational_factorization.h>
#else
#include <LiDIA/bigint.h>
#include <LiDIA/rational_factorization.h>
#endif

class galois_field
{
  /**
  ** the C++ type we use to represent a Galois field
  **/

  friend class gf_p_base;
  friend class gf_n_base;


  bigint                          p;
  lidia_size_t                    n;
  bigint                          p_pow_n;

  LIDIA_MUTABLE rational_factorization  p_pow_n_minus_1;
  LIDIA_MUTABLE lidia_size_t            ref_counter;

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

  static bigint greatest_divisor_of_1_coprime_to_2(const bigint &a, const bigint &b);
  
  public:

  /**
  ** constructors and destructor
  **/

  galois_field();
  galois_field(const bigint & characteristic, lidia_size_t degree = 1);
  galois_field(const bigint & characteristic, lidia_size_t degree, 
     const rational_factorization & fact);
  galois_field(const rational_factorization & fact);
  galois_field(const galois_field & K);
  ~galois_field();

  /**
  ** access functions
  **/

  const bigint &                  characteristic()               const;
  const lidia_size_t &            degree()                       const;
  const bigint &                  number_of_elements()           const;
  const rational_factorization  & factorization_of_mult_order()  const;
  

  /**
  ** assignment
  **/

  void assign(const galois_field & K);

  /**
  ** input / output
  **/

  friend istream & operator >> (istream & in, galois_field & K);
  friend ostream & operator << (ostream & out, const galois_field & K);

};

#endif

