/****************************************************************************
**
*W  objects.h                   GAP source                   Martin Schönert
**
**
*Y  Copyright (C)  1996,  Lehrstuhl D für Mathematik,  RWTH Aachen,  Germany
*Y  (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
*Y  Copyright (C) 2002 The GAP Group
**
**  This file defines the functions of the objects package.
**
**  The objects package is the part that defines the 'Obj' type,  the objects
**  types  (i.e., the numbers  that  Gasman needs  to distinguish types), the
**  dispatcher for the printing of objects, etc.
*/

#ifndef libGAP_GAP_OBJECTS_H
#define libGAP_GAP_OBJECTS_H


/****************************************************************************
**

*T  Obj . . . . . . . . . . . . . . . . . . . . . . . . . . . type of objects
**
**  'Obj' is the type of objects.
**
**  The following is defined in "system.h"
**
#define Obj             Bag
*/


/****************************************************************************
**

*F  IS_INTOBJ( <o> )  . . . . . . . .  test if an object is an integer object
**
**  'IS_INTOBJ' returns 1 if the object <o> is an (immediate) integer object,
**  and 0 otherwise.
*/
#define libGAP_IS_INTOBJ(o) \
    ((libGAP_Int)(o) & 0x01)



/****************************************************************************
**
*F  ARE_INTOBJS( <o1>, <o2> ) . . . . test if two objects are integer objects
**
**  'ARE_INTOBJS' returns 1 if the objects <o1> and <o2> are both (immediate)
**  integer objects.
*/
#define libGAP_ARE_INTOBJS(o1,o2) \
    ((libGAP_Int)(o1) & (libGAP_Int)(o2) & 0x01)


/****************************************************************************
**
*F  INTOBJ_INT( <i> ) . . . . . . .  convert a C integer to an integer object
**
**  'INTOBJ_INT' converts the C integer <i> to an (immediate) integer object.
*/
#define libGAP_INTOBJ_INT(i) \
    ((libGAP_Obj)(((libGAP_Int)(i) << 2) + 0x01))


/****************************************************************************
**
*F  INT_INTOBJ( <o> ) . . . . . . .  convert an integer object to a C integer
**
**  'INT_INTOBJ' converts the (immediate) integer object <o> to a C integer.
*/
/* Note that the C standard does not define what >> does here if the
 * value is negative. So we have to be careful if the C compiler
 * chooses to do a logical right shift. */
#if HAVE_ARITHRIGHTSHIFT
#define libGAP_INT_INTOBJ(o) \
    ((libGAP_Int)(o) >> 2)
#else
#define libGAP_INT_INTOBJ(o) \
    (((libGAP_Int)(o)-1) / 4)
#endif



/****************************************************************************
**
*F  EQ_INTOBJS( <o>, <l>, <r> ) . . . . . . . . . compare two integer objects
**
**  'EQ_INTOBJS' returns 'True' if the  (immediate)  integer  object  <l>  is
**  equal to the (immediate) integer object <r> and  'False'  otherwise.  The
**  result is also stored in <o>.
*/
#define libGAP_EQ_INTOBJS(o,l,r) \
    ((o) = (((libGAP_Int)(l)) == ((libGAP_Int)(r)) ? libGAP_True : libGAP_False))


/****************************************************************************
**
*F  LT_INTOBJS( <o>, <l>, <r> ) . . . . . . . . . compare two integer objects
**
**  'LT_INTOBJS' returns 'True' if the  (immediate)  integer  object  <l>  is
**  less than the (immediate) integer object <r> and  'False' otherwise.  The
**  result is also stored in <o>.
*/
#define libGAP_LT_INTOBJS(o,l,r) \
    ((o) = (((libGAP_Int)(l)) <  ((libGAP_Int)(r)) ? libGAP_True : libGAP_False))


/****************************************************************************
**
*F  SUM_INTOBJS( <o>, <l>, <r> )  . . . . . . . .  sum of two integer objects
**
**  'SUM_INTOBJS' returns  1  if  the  sum  of  the  (imm.)  integer  objects
**  <l> and <r> can be stored as (immediate) integer object  and 0 otherwise.
**  The sum itself is stored in <o>.
*/
#if HAVE_ARITHRIGHTSHIFT
#define libGAP_SUM_INTOBJS(o,l,r)             \
    ((o) = (libGAP_Obj)((libGAP_Int)(l)+(libGAP_Int)(r)-1), \
    (((libGAP_Int)(o) << 1) >> 1) == (libGAP_Int)(o) )
#else
#define libGAP_SUM_INTOBJS(o,l,r)             \
    ((o) = (libGAP_Obj)((libGAP_Int)(l)+(libGAP_Int)(r)-1), \
     ((((libGAP_UInt) (o)) >> (sizeof(libGAP_UInt)*8-2))-1) > 1)
#endif


/****************************************************************************
**
*F  DIFF_INTOBJS( <o>, <l>, <r> ) . . . . . difference of two integer objects
**
**  'DIFF_INTOBJS' returns 1 if the difference of the (imm.) integer  objects
**  <l> and <r> can be stored as (immediate) integer object  and 0 otherwise.
**  The difference itself is stored in <o>.
*/
#if HAVE_ARITHRIGHTSHIFT
#define libGAP_DIFF_INTOBJS(o,l,r)            \
    ((o) = (libGAP_Bag)((libGAP_Int)(l)-(libGAP_Int)(r)+1), \
     (((libGAP_Int)(o) << 1) >> 1) == (libGAP_Int)(o) )
#else
#define libGAP_DIFF_INTOBJS(o,l,r)            \
    ((o) = (libGAP_Bag)((libGAP_Int)(l)-(libGAP_Int)(r)+1), \
     ((((libGAP_UInt) (o)) >> (sizeof(libGAP_UInt)*8-2))-1) > 1)
#endif


/****************************************************************************
**
*F  PROD_INTOBJS( <o>, <l>, <r> ) . . . . . .  product of two integer objects
**
**  'PROD_INTOBJS' returns 1 if the product of  the  (imm.)  integer  objects
**  <l> and <r> can be stored as (immediate) integer object  and 0 otherwise.
**  The product itself is stored in <o>.
*/

#ifdef libGAP_SYS_IS_64_BIT
#define libGAP_HALF_A_WORD 32
#else
#define libGAP_HALF_A_WORD 16
#endif

#if HAVE_ARITHRIGHTSHIFT
static inline libGAP_Obj libGAP_prod_intobjs(libGAP_Int l, libGAP_Int r)
{
  libGAP_Int prod;
  if (l == (libGAP_Int)libGAP_INTOBJ_INT(0) || r == (libGAP_Int)libGAP_INTOBJ_INT(0))
    return libGAP_INTOBJ_INT(0);
  if (l == (libGAP_Int)libGAP_INTOBJ_INT(1))
    return (libGAP_Obj)r;
  if (r == (libGAP_Int)libGAP_INTOBJ_INT(1))
    return (libGAP_Obj)l;
  prod = ((libGAP_Int)((libGAP_UInt)l >> 2) * ((libGAP_UInt)r-1)+1);
  if ((prod << 1)>> 1 !=  prod)
    return (libGAP_Obj) 0;
  if ((((libGAP_Int)l)<<libGAP_HALF_A_WORD)>>libGAP_HALF_A_WORD == (libGAP_Int) l &&
      (((libGAP_Int)r)<<libGAP_HALF_A_WORD)>>libGAP_HALF_A_WORD == (libGAP_Int) r)
    return (libGAP_Obj) prod;
  if ((prod -1) / (l >> 2) == r-1)
    return (libGAP_Obj) prod;
  else
    return (libGAP_Obj) 0;
}
#else
static inline libGAP_Obj libGAP_prod_intobjs(libGAP_Int l, libGAP_Int r)
{
  libGAP_Int prod;
  if (l == (libGAP_Int)libGAP_INTOBJ_INT(0) || r == (libGAP_Int)libGAP_INTOBJ_INT(0))
    return libGAP_INTOBJ_INT(0);
  if (l == (libGAP_Int)libGAP_INTOBJ_INT(1))
    return (libGAP_Obj)r;
  if (r == (libGAP_Int)libGAP_INTOBJ_INT(1))
    return (libGAP_Obj)l;
  prod = ((libGAP_Int)((libGAP_UInt)l >> 2) * ((libGAP_UInt)r-1)+1);
  if (((((libGAP_UInt) (prod)) >> (sizeof(libGAP_UInt)*8-2))-1) <= 1)
    return (libGAP_Obj) 0;
  if ((((libGAP_Int)l)<<libGAP_HALF_A_WORD)>>libGAP_HALF_A_WORD == (libGAP_Int) l &&
      (((libGAP_Int)r)<<libGAP_HALF_A_WORD)>>libGAP_HALF_A_WORD == (libGAP_Int) r)
    return (libGAP_Obj) prod;
  if ((prod-1) / ((l-1)/4) == r-1)
    return (libGAP_Obj) prod;
  else
    return (libGAP_Obj) 0;
}
#endif

#define libGAP_PROD_INTOBJS( o, l, r) ((o) = libGAP_prod_intobjs((libGAP_Int)(l),(libGAP_Int)(r)), \
                                  (o) != (libGAP_Obj) 0)
   
/****************************************************************************
**
*F  IS_FFE( <o> ) . . . . . . . . test if an object is a finite field element
**
**  'IS_FFE'  returns 1  if the  object <o>  is  an  (immediate) finite field
**  element and 0 otherwise.
*/
#define libGAP_IS_FFE(o)               \
                        ((libGAP_Int)(o) & 0x02)


/****************************************************************************
**

*S  T_<name>  . . . . . . . . . . . . . . . . symbolic names for object types
*S  FIRST_CONSTANT_TNUM, LAST_CONSTANT_TNUM . . . . range of constant   types
*S  FIRST_RECORD_TNUM,   LAST_RECORD_TNUM . . . . . range of record     types
*S  FIRST_LIST_TNUM,     LAST_LIST_TNUM . . . . . . range of list       types
*S  FIRST_EXTERNAL_TNUM, LAST_EXTERNAL_TNUM . . . . range of external   types
*S  FIRST_REAL_TNUM,     LAST_REAL_TNUM . . . . . . range of real       types
*S  FIRST_VIRTUAL_TNUM,  LAST_VIRTUAL_TNUM  . . . . range of virtual    types
*S  FIRST_IMM_MUT_TNUM,  LAST_IMM_MUT_TNUM  . . . . range of im/mutable types
**
**  For every type of objects there is a symbolic name defined for this type.
**
**  'FIRST_CONSTANT_TNUM'  is  the first   type  of constant  objects,  e.g.,
**  integers, booleans, and functions.  'LAST_CONSTANT_TNUM' is the last type
**  of constant objects.
**
**  'FIRST_RECORD_TNUM' is the first type of record objects,  currently  only
**  plain records.  'LAST_RECORD_TNUM' is the last type of record objects.
**
**  'FIRST_LIST_TNUM' is the first type of list objects, e.g.,  plain  lists,
**  ranges, boolean lists, and strings.  'LAST_LIST_TNUM' is the last type of
**  list objects.
**
**  'FIRST_EXTERNAL_TNUM' is the  first type  of external objects,  currently
**  only   component   objects,  positional   objects,    and data   objects.
**  'LAST_EXTERNAL_TNUM' is the last type of external objects.
**
**  'FIRST_REAL_TNUM' is the first  real  type, namely 'FIRST_CONSTANT_TNUM'.
**  'LAST_REAL_TNUM'  is the last   real  type, namely  'LAST_EXTERNAL_TNUM'.
**
**  'FIRST_VIRTUAL_TNUM' is   the first virtual type.  'LAST_VIRTUAL_TNUM' is
**  the last virtual type.
**
**  'FIRST_IMM_MUT_TNUM'  is the first  real  internal type of objects  which
**  might be mutable, 'LAST_IMM_MUT_TNUM' is the last such type.
**
**  The types *must* be sorted in this order, i.e., first the constant types,
**  then the record types, then the list types,  then the external types, and
**  finally the virtual types.
*/
#define libGAP_FIRST_REAL_TNUM         0

#define libGAP_FIRST_CONSTANT_TNUM     ((libGAP_UInt)0)
#define libGAP_T_INT                   (libGAP_FIRST_CONSTANT_TNUM+ 0)    /* immediate */
#define libGAP_T_INTPOS                (libGAP_FIRST_CONSTANT_TNUM+ 1)
#define libGAP_T_INTNEG                (libGAP_FIRST_CONSTANT_TNUM+ 2)
#define libGAP_T_RAT                   (libGAP_FIRST_CONSTANT_TNUM+ 3)
#define libGAP_T_CYC                   (libGAP_FIRST_CONSTANT_TNUM+ 4)
#define libGAP_T_FFE                   (libGAP_FIRST_CONSTANT_TNUM+ 5)    /* immediate */
#define libGAP_T_PERM2                 (libGAP_FIRST_CONSTANT_TNUM+ 6)
#define libGAP_T_PERM4                 (libGAP_FIRST_CONSTANT_TNUM+ 7)
#define libGAP_T_BOOL                  (libGAP_FIRST_CONSTANT_TNUM+ 8)
#define libGAP_T_CHAR                  (libGAP_FIRST_CONSTANT_TNUM+ 9)
#define libGAP_T_FUNCTION              (libGAP_FIRST_CONSTANT_TNUM+10)
#define libGAP_T_FLAGS                 (libGAP_FIRST_CONSTANT_TNUM+11)
#define libGAP_T_MACFLOAT              (libGAP_FIRST_CONSTANT_TNUM+12)
#define libGAP_T_LVARS                 (libGAP_FIRST_CONSTANT_TNUM+13)   
#define libGAP_T_SINGULAR              (libGAP_FIRST_CONSTANT_TNUM+14)   
#define libGAP_T_POLYMAKE              (libGAP_FIRST_CONSTANT_TNUM+15)
#define libGAP_T_TRANS2                (libGAP_FIRST_CONSTANT_TNUM+16)
#define libGAP_T_TRANS4                (libGAP_FIRST_CONSTANT_TNUM+17)
#define libGAP_T_PPERM2                (libGAP_FIRST_CONSTANT_TNUM+18)
#define libGAP_T_PPERM4                (libGAP_FIRST_CONSTANT_TNUM+19)
#define libGAP_T_SPARE1                (libGAP_FIRST_CONSTANT_TNUM+20)
#define libGAP_T_SPARE2                (libGAP_FIRST_CONSTANT_TNUM+21)
#define libGAP_T_SPARE3                (libGAP_FIRST_CONSTANT_TNUM+22)
#define libGAP_T_SPARE4                (libGAP_FIRST_CONSTANT_TNUM+23)
#define libGAP_LAST_CONSTANT_TNUM      (libGAP_T_SPARE4)

#define libGAP_IMMUTABLE               1

#define libGAP_FIRST_IMM_MUT_TNUM      (libGAP_LAST_CONSTANT_TNUM+1)    /* Should be even */
#define libGAP_FIRST_RECORD_TNUM       libGAP_FIRST_IMM_MUT_TNUM
#define libGAP_T_PREC                  (libGAP_FIRST_RECORD_TNUM+ 0)
#define libGAP_LAST_RECORD_TNUM        (libGAP_T_PREC+libGAP_IMMUTABLE)

#define libGAP_FIRST_LIST_TNUM         (libGAP_LAST_RECORD_TNUM+1)
#define libGAP_FIRST_PLIST_TNUM        libGAP_FIRST_LIST_TNUM
#define libGAP_T_PLIST                 (libGAP_FIRST_LIST_TNUM+ 0)
#define libGAP_T_PLIST_NDENSE          (libGAP_FIRST_LIST_TNUM+ 2)
#define libGAP_T_PLIST_DENSE           (libGAP_FIRST_LIST_TNUM+ 4)
#define libGAP_T_PLIST_DENSE_NHOM      (libGAP_FIRST_LIST_TNUM+ 6)
#define libGAP_T_PLIST_DENSE_NHOM_SSORT (libGAP_FIRST_LIST_TNUM+8 )
#define libGAP_T_PLIST_DENSE_NHOM_NSORT (libGAP_FIRST_LIST_TNUM+10)
#define libGAP_T_PLIST_EMPTY           (libGAP_FIRST_LIST_TNUM+12)
#define libGAP_T_PLIST_HOM             (libGAP_FIRST_LIST_TNUM+14)
#define libGAP_T_PLIST_HOM_NSORT       (libGAP_FIRST_LIST_TNUM+16)
#define libGAP_T_PLIST_HOM_SSORT       (libGAP_FIRST_LIST_TNUM+18)
#define libGAP_T_PLIST_TAB             (libGAP_FIRST_LIST_TNUM+20)
#define libGAP_T_PLIST_TAB_NSORT       (libGAP_FIRST_LIST_TNUM+22)
#define libGAP_T_PLIST_TAB_SSORT       (libGAP_FIRST_LIST_TNUM+24)
#define libGAP_T_PLIST_TAB_RECT             (libGAP_FIRST_LIST_TNUM+26)
#define libGAP_T_PLIST_TAB_RECT_NSORT       (libGAP_FIRST_LIST_TNUM+28)
#define libGAP_T_PLIST_TAB_RECT_SSORT       (libGAP_FIRST_LIST_TNUM+30)
#define libGAP_T_PLIST_CYC             (libGAP_FIRST_LIST_TNUM+32)
#define libGAP_T_PLIST_CYC_NSORT       (libGAP_FIRST_LIST_TNUM+34)
#define libGAP_T_PLIST_CYC_SSORT       (libGAP_FIRST_LIST_TNUM+36)
#define libGAP_T_PLIST_FFE             (libGAP_FIRST_LIST_TNUM+38)
#define libGAP_LAST_PLIST_TNUM         (libGAP_T_PLIST_FFE+libGAP_IMMUTABLE)
#define libGAP_T_RANGE_NSORT           (libGAP_FIRST_LIST_TNUM+40)
#define libGAP_T_RANGE_SSORT           (libGAP_FIRST_LIST_TNUM+42)
#define libGAP_T_BLIST                 (libGAP_FIRST_LIST_TNUM+44)
#define libGAP_T_BLIST_NSORT           (libGAP_FIRST_LIST_TNUM+46)
#define libGAP_T_BLIST_SSORT           (libGAP_FIRST_LIST_TNUM+48)
#define libGAP_T_STRING                (libGAP_FIRST_LIST_TNUM+50)
#define libGAP_T_STRING_NSORT          (libGAP_FIRST_LIST_TNUM+52)
#define libGAP_T_STRING_SSORT          (libGAP_FIRST_LIST_TNUM+54)
#define libGAP_LAST_LIST_TNUM          (libGAP_T_STRING_SSORT+libGAP_IMMUTABLE)
#define libGAP_LAST_IMM_MUT_TNUM       libGAP_LAST_LIST_TNUM

/* IMMUTABLE is not used for external types but keep the parity */
#define libGAP_FIRST_EXTERNAL_TNUM     (libGAP_LAST_LIST_TNUM+1)
#define libGAP_T_COMOBJ                (libGAP_FIRST_EXTERNAL_TNUM+ 0)
#define libGAP_T_POSOBJ                (libGAP_FIRST_EXTERNAL_TNUM+ 1)
#define libGAP_T_DATOBJ                (libGAP_FIRST_EXTERNAL_TNUM+ 2)
#define libGAP_T_WPOBJ                 (libGAP_FIRST_EXTERNAL_TNUM+ 3)
     /* #define T_DUMMYOBJ              (FIRST_EXTERNAL_TNUM+ 4)
        remove to get parity right */
#define libGAP_LAST_EXTERNAL_TNUM      libGAP_T_WPOBJ
#define libGAP_LAST_REAL_TNUM          libGAP_LAST_EXTERNAL_TNUM
#define libGAP_LAST_VIRTUAL_TNUM libGAP_LAST_EXTERNAL_TNUM

#define libGAP_FIRST_COPYING_TNUM      (libGAP_LAST_REAL_TNUM + 1)
#define libGAP_COPYING                 (libGAP_FIRST_COPYING_TNUM - libGAP_FIRST_RECORD_TNUM)
#define libGAP_LAST_COPYING_TNUM       (libGAP_LAST_REAL_TNUM + libGAP_COPYING)

/* share the same numbers between `COPYING' and `TESTING' */
#define libGAP_FIRST_TESTING_TNUM      libGAP_FIRST_COPYING_TNUM
#define libGAP_TESTING                 libGAP_COPYING
#define libGAP_LAST_TESTING_TNUM       libGAP_LAST_COPYING_TNUM



/****************************************************************************
**

*F  F_MUTABLE . . . . . . . . . . . . . . . . . . . . . . .  IsMutableObjFilt
*/
#define libGAP_F_MUTABLE       1


/****************************************************************************
**
*F  F_EMPTY . . . . . . . . . . . . . . . . . . . . . . . . . . . IsEmptyProp
*/
#define libGAP_F_EMPTY         2
#define libGAP_F_NOT_EMPTY     3


/****************************************************************************
**
*F  F_SSORT . . . . . . . . . . . . . . . . . . . . . . . . . . . IsSSortProp
*/
#define libGAP_F_SSORT         4
#define libGAP_F_NOT_SSORT     5


/****************************************************************************
**
*F  F_DENSE . . . . . . . . . . . . . . . . . . . . . . . . . . . IsDenseProp
*/
#define libGAP_F_DENSE         6
#define libGAP_F_NOT_DENSE     7


/****************************************************************************
**
*F  F_HOMOG . . . . . . . . . . . . . . . . . . . . . . . . . . . IsHomogProp
*/
#define libGAP_F_HOMOG         8
#define libGAP_F_NOT_HOMOG     9


/****************************************************************************
**
*F  F_TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . IsTableProp
*/
#define libGAP_F_TABLE         10
#define libGAP_F_NOT_TABLE     11

/****************************************************************************
**
*F  F_RECT . . . . . . . . . . . . . . . . . . . . . . IsRectangularTableProp
*/
#define libGAP_F_RECT         12
#define libGAP_F_NOT_RECT     13


/****************************************************************************
**

*F  TNUM_OBJ( <obj> ) . . . . . . . . . . . . . . . . . . . type of an object
**
**  'TNUM_OBJ' returns the type of the object <obj>.
*/
#define libGAP_TNUM_OBJ(obj)   (libGAP_IS_INTOBJ( obj ) ? libGAP_T_INT : \
                         (libGAP_IS_FFE( obj ) ? libGAP_T_FFE : libGAP_TNUM_BAG( obj )))


/****************************************************************************
**
*F  TNAM_OBJ( <obj> ) . . . . . . . . . . . . . name of the type of an object
*/
#define libGAP_TNAM_OBJ(obj)   (libGAP_InfoBags[libGAP_TNUM_OBJ(obj)].name)


/****************************************************************************
**
*F  SIZE_OBJ( <obj> ) . . . . . . . . . . . . . . . . . . . size of an object
**
**  'SIZE_OBJ' returns the size of the object <obj>.
*/
#define libGAP_SIZE_OBJ        libGAP_SIZE_BAG


/****************************************************************************
**
*F  ADDR_OBJ( <obj> ) . . . . . . . . . . . . . absolute address of an object
**
**  'ADDR_OBJ' returns the absolute address of the memory block of the object
**  <obj>.
*/
#define libGAP_ADDR_OBJ(bag)        libGAP_PTR_BAG(bag)


/****************************************************************************
**

*F  FAMILY_TYPE( <kind> ) . . . . . . . . . . . . . . . . .  family of a kind
**
**  'FAMILY_TYPE' returns the family of the kind <kind>.
*/
#define libGAP_FAMILY_TYPE(kind)       libGAP_ELM_PLIST( kind, 1 )


/****************************************************************************
**
*F  FAMILY_OBJ( <obj> ) . . . . . . . . . . . . . . . . . family of an object
*/
#define libGAP_FAMILY_OBJ(obj)         libGAP_FAMILY_TYPE( libGAP_TYPE_OBJ(obj) )


/****************************************************************************
**
*F  FLAGS_TYPE( <kind> )  . . . . . . . . . . .  flags boolean list of a kind
**
**  'FLAGS_TYPE' returns the flags boolean list of the kind <kind>.
*/
#define libGAP_FLAGS_TYPE(kind)        libGAP_ELM_PLIST( kind, 2 )


/****************************************************************************
**
*F  SHARED_TYPE( <kind> ) . . . . . . . . . . . . . . . shared data of a kind
**
**  'SHARED_TYPE' returns the shared data of the kind <kind>.
XXX nowhere used, throw away??? (FL)
*/
/* #define SHARED_TYPE(kind)       ELM_PLIST( kind, 3 )
*/                        
                        
/****************************************************************************
**
*F  ID_TYPE( <kind> ) . . . . . . . . . . . . . . . . . . . . .  id of a kind
**
**  'ID_TYPE' returns the ID of  a kind.  Warning: if  GAP runs out of ID  it
**  will renumber all IDs.  Therefore the  corresponding routine must excatly
**  know where such numbers are stored.
*/
#define libGAP_ID_TYPE(kind)           libGAP_ELM_PLIST( kind, 4 )


/****************************************************************************
**
*F  TYPE_OBJ( <obj> ) . . . . . . . . . . . . . . . . . . . kind of an object
**
**  'TYPE_OBJ' returns the kind of the object <obj>.
*/
#define libGAP_TYPE_OBJ(obj)   ((*libGAP_TypeObjFuncs[ libGAP_TNUM_OBJ(obj) ])( obj ))

extern libGAP_Obj (*libGAP_TypeObjFuncs[ libGAP_LAST_REAL_TNUM+1 ]) ( libGAP_Obj obj );


/****************************************************************************
**

*F  MUTABLE_TNUM( <type> )  . . . . . . . . . . mutable type of internal type
*/
#define libGAP_MUTABLE_TNUM(type) \
    ( ( (type) < libGAP_FIRST_IMM_MUT_TNUM ? (type) : \
       ( libGAP_LAST_IMM_MUT_TNUM < (type) ? (type) : \
        ( ((((type)-libGAP_T_PLIST)&(~libGAP_IMMUTABLE))+libGAP_T_PLIST) ) ) ) )


/****************************************************************************
**
*F  IMMUTABLE_TNUM( <type> )  . . . . . . . . immutable type of internal type
*/
#define libGAP_IMMUTABLE_TNUM(type) \
    ( ( (type) < libGAP_FIRST_IMM_MUT_TNUM ? (type) : \
       ( libGAP_LAST_IMM_MUT_TNUM < (type) ? (type) : \
        ( ((((type)-libGAP_T_PLIST)|libGAP_IMMUTABLE)+libGAP_T_PLIST) ) ) ) )

/****************************************************************************
**
*F  MakeImmutable( <obj> ) . . . . . . . . . . . . . make an object immutable
*/
extern void libGAP_MakeImmutable( libGAP_Obj obj );

/****************************************************************************
**
*F  IS_MUTABLE_OBJ( <obj> ) . . . . . . . . . . . . . .  is an object mutable
**
**  'IS_MUTABLE_OBJ' returns   1 if the object  <obj> is mutable   (i.e., can
**  change due to assignments), and 0 otherwise.
*/
#define libGAP_IS_MUTABLE_OBJ(obj) \
                        ((*libGAP_IsMutableObjFuncs[ libGAP_TNUM_OBJ(obj) ])( obj ))

extern libGAP_Int (*libGAP_IsMutableObjFuncs[ libGAP_LAST_REAL_TNUM+1 ]) ( libGAP_Obj obj );

/****************************************************************************
**
*V  SaveObjFuncs (<type>) . . . . . . . . . . . . . functions to save objects
**
** 'SaveObjFuncs' is the dispatch table that  contains, for every type
**  of  objects, a pointer to the saving function for objects of that type
**  These should not handle the file directly, but should work via the
**  functions 'SaveObjRef', 'SaveUInt<n>' (<n> = 1,2,4 or 8), and others
**  to be determined. Their role is to identify the C types of the various
**  parts of the bag, and perhaps to leave out some information that does
**  not need to be saved. By the time this function is called, the bag
**  size and type have already been saved
**  No saving function may allocate any bag
*/

extern void (*libGAP_SaveObjFuncs[ 256 ]) (libGAP_Obj obj);

extern void libGAP_SaveObjError ( libGAP_Obj obj );


/****************************************************************************
**
*V  LoadObjFuncs (<type>) . . . . . . . . . . . . . functions to load objects
**
** 'LoadObjFuncs' is the dispatch table that  contains, for every type
**  of  objects, a pointer to the loading function for objects of that type
**  These should not handle the file directly, but should work via the
**  functions 'LoadObjRef', 'LoadUInt<n>' (<n> = 1,2,4 or 8), and others
**  to be determined. Their role is to reinstall the information in the bag
**  and reconstruct anything that was left out. By the time this function is
**  called, the bag size and type have already been loaded and the bag argument
**  contains the bag in question
**  No loading function may allocate any bag
*/

extern void (*libGAP_LoadObjFuncs[ 256 ]) (libGAP_Bag bag);

extern void libGAP_LoadObjError (
                   libGAP_Bag bag
                   );

/****************************************************************************
**
*F  IS_COPYABLE_OBJ( <obj> )  . . . . . . . . . . . . . is an object copyable
**
**  'IS_COPYABLE_OBJ' returns 1 if the object <obj> is copyable (i.e., can be
**  copied into a mutable object), and 0 otherwise.
*/
#define libGAP_IS_COPYABLE_OBJ(obj) \
                        ((libGAP_IsCopyableObjFuncs[ libGAP_TNUM_OBJ(obj) ])( obj ))

extern libGAP_Int (*libGAP_IsCopyableObjFuncs[ libGAP_LAST_REAL_TNUM+1 ]) ( libGAP_Obj obj );


/****************************************************************************
**

*F  SHALLOW_COPY_OBJ( <obj> ) . . . . . . .  make a shallow copy of an object
**
**  'SHALLOW_COPY_OBJ' makes a shallow copy of the object <obj>.
*/
#define libGAP_SHALLOW_COPY_OBJ(obj) \
                        ((*libGAP_ShallowCopyObjFuncs[ libGAP_TNUM_OBJ(obj) ])( obj ))


/****************************************************************************
**
*V  ShallowCopyObjFuncs[<type>] . . . . . . . . . .  shallow copier functions
*/
extern libGAP_Obj (*libGAP_ShallowCopyObjFuncs[ libGAP_LAST_REAL_TNUM+1 ]) ( libGAP_Obj obj );


/****************************************************************************
**

*F  CopyObj( <obj> )  . . . . . . . . . . make a structural copy of an object
**
**  'CopyObj' returns a  structural (deep) copy  of the object <obj>, i.e., a
**  recursive copy that preserves the structure.
*/
extern libGAP_Obj libGAP_CopyObj (
    libGAP_Obj                 obj,
    libGAP_Int                 mut );


/****************************************************************************
**
*F  COPY_OBJ(<obj>) . . . . . . . . . . . make a structural copy of an object
**
**  'COPY_OBJ'  implements  the first pass  of  'CopyObj', i.e., it makes the
**  structural copy of <obj> and marks <obj> as already copied.
**
**  Note that 'COPY_OBJ' and 'CLEAN_OBJ' are macros, so do not call them with
**  arguments that have side effects.
*/
#define libGAP_COPY_OBJ(obj,mut) \
                        ((*libGAP_CopyObjFuncs[ libGAP_TNUM_OBJ(obj) ])( obj, mut ))


/****************************************************************************
**
*F  CLEAN_OBJ(<obj>)  . . . . . . . . . . . . . clean up object after copying
**
**  'CLEAN_OBJ' implements the second pass of 'CopyObj', i.e., it removes the
**  mark <obj>.
**
**  Note that 'COPY_OBJ' and 'CLEAN_OBJ' are macros, so do not call them with
**  arguments that have side effects.
*/
#define libGAP_CLEAN_OBJ(obj) \
                        ((*libGAP_CleanObjFuncs[ libGAP_TNUM_OBJ(obj) ])( obj ))



/****************************************************************************
**
*V  CopyObjFuncs[<type>]  . . . . . . . . . . . .  table of copying functions
**
**  A package implementing a nonconstant object type <type> must provide such
**  functions      and     install them     in    'CopyObjFuncs[<type>]'  and
**  'CleanObjFuncs[<type>]'.
**
**  The function called  by 'COPY_OBJ' should  first create a  copy of <obj>,
**  somehow mark   <obj> as having  already been  copied, leave  a forwarding
**  pointer  to  the  copy  in <obj>,   and  then  copy all  subobjects  with
**  'COPY_OBJ'  recursively.  If  called   for an already  marked  object, it
**  should simply return the value  of the forward  pointer.  It should *not*
**  clear the mark, this is the job of 'CLEAN_OBJ' later.
**
**  The function  called by 'CLEAN_OBJ' should   clear the mark  left by the
**  corresponding 'COPY_OBJ' function,   remove the forwarding  pointer, and
**  then call 'CLEAN_OBJ'  for all subobjects recursively.  If called for an
**  already unmarked object, it should simply return.
*/
extern libGAP_Obj (*libGAP_CopyObjFuncs[ libGAP_LAST_REAL_TNUM+libGAP_COPYING+1 ]) ( libGAP_Obj obj, libGAP_Int mut );



/****************************************************************************
**
*V  CleanObjFuncs[<type>] . . . . . . . . . . . . table of cleaning functions
*/
extern void (*libGAP_CleanObjFuncs[ libGAP_LAST_REAL_TNUM+libGAP_COPYING+1 ]) ( libGAP_Obj obj );


extern void (*libGAP_MakeImmutableObjFuncs[ libGAP_LAST_REAL_TNUM+1 ]) (libGAP_Obj obj );

/****************************************************************************
**
*F  PrintObj( <obj> ) . . . . . . . . . . . . . . . . . . . . print an object
**
**  'PrintObj' prints the object <obj>.
*/
extern void libGAP_PrintObj (
            libGAP_Obj                 obj );


/****************************************************************************
**
*V  PrintObjFuncs[<type>] . . . . . . . .  printer for objects of type <type>
**
**  'PrintObjFuncs' is  the dispatch  table that  contains  for every type of
**  objects a pointer to the printer for objects of this  type.  The  printer
**  is the function '<func>(<obj>)' that should be called to print the object
**  <obj> of this type.
*/
extern libGAP_Obj  libGAP_PrintObjThis;

extern libGAP_Int  libGAP_PrintObjIndex;
extern libGAP_Int  libGAP_PrintObjDepth;

extern libGAP_Int  libGAP_PrintObjFull;

extern void (* libGAP_PrintObjFuncs [ libGAP_LAST_REAL_TNUM  +1 ]) ( libGAP_Obj obj );


/****************************************************************************
**
*F  ViewObj( <obj> ) . . . . . . . . . . . . . . . . . . . . view an object
**
**  'ViewObj' views the object <obj>.
*/
extern void libGAP_ViewObj (
            libGAP_Obj                 obj );




/****************************************************************************
**
*V  PrintPathFuncs[<type>]  . . . . . . printer for subobjects of type <type>
**
**  'PrintPathFuncs'  is   the   dispatch table  that     contains for  every
**  appropriate type of objects a pointer to  the path printer for objects of
**  that type.  The path  printer is the function '<func>(<obj>,<indx>)' that
**  should be  called  to print  the  selector   that selects  the  <indx>-th
**  subobject of the object <obj> of this type.
**
**  These are also used for viewing
*/
extern void (* libGAP_PrintPathFuncs [ libGAP_LAST_REAL_TNUM  +1 ]) (
    libGAP_Obj                 obj,
    libGAP_Int                 indx );


/****************************************************************************
**

*F  IS_COMOBJ( <obj> )  . . . . . . . . . . . is an object a component object
*/
#define libGAP_IS_COMOBJ(obj)            (libGAP_TNUM_OBJ(obj) == libGAP_T_COMOBJ)


/****************************************************************************
**
*F  TYPE_COMOBJ( <obj> )  . . . . . . . . . . . .  kind of a component object
*/
#define libGAP_TYPE_COMOBJ(obj)          libGAP_ADDR_OBJ(obj)[0]


/****************************************************************************
**
*F  SET_TYPE_COMOBJ( <obj>, <val> ) . . .  set the kind of a component object
*/
#define libGAP_SET_TYPE_COMOBJ(obj,val)  (libGAP_ADDR_OBJ(obj)[0] = (val))


/****************************************************************************
**

*F  IS_POSOBJ( <obj> )  . . . . . . . . . .  is an object a positional object
*/
#define libGAP_IS_POSOBJ(obj)            (libGAP_TNUM_OBJ(obj) == libGAP_T_POSOBJ)


/****************************************************************************
**
*F  TYPE_POSOBJ( <obj> )  . . . . . . . . . . . . kind of a positional object
*/
#define libGAP_TYPE_POSOBJ(obj)          libGAP_ADDR_OBJ(obj)[0]


/****************************************************************************
**
*F  SET_TYPE_POSOBJ( <obj>, <val> ) . . . set the kind of a positional object
*/
#define libGAP_SET_TYPE_POSOBJ(obj,val)  (libGAP_ADDR_OBJ(obj)[0] = (val))
 

/****************************************************************************
**

*F  IS_DATOBJ( <obj> )  . . . . . . . . . . . . .  is an object a data object
*/
#define libGAP_IS_DATOBJ(obj)            (libGAP_TNUM_OBJ(obj) == libGAP_T_DATOBJ)


/****************************************************************************
**
*F  TYPE_DATOBJ( <obj> )  . . . . . . . . . . . . . . . kind of a data object
*/
#define libGAP_TYPE_DATOBJ(obj)          libGAP_ADDR_OBJ(obj)[0]


/****************************************************************************
**
*F  TYPE_ANYOBJ( <obj> )  . . . . . . . . . . . . .kind of an external object
**
** This is a hack which relies on the fact that TYPE_COMOBJ, TYPE_DATOBJ and
** TYPE_POSOBJ are actually the same
*/

#define libGAP_TYPE_ANYOBJ(obj)          libGAP_ADDR_OBJ(obj)[0]


/****************************************************************************
**
*F  SET_TYPE_DATOBJ( <obj>, <val> )  . . . . .  set the kind of a data object
*/
#define libGAP_SET_TYPE_DATOBJ(obj,val)  (libGAP_ADDR_OBJ(obj)[0] = (val))


/****************************************************************************
**

*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
*/


/****************************************************************************
**

*F  InitInfoObjects() . . . . . . . . . . . . . . . . table of init functions
*/
libGAP_StructInitInfo * libGAP_InitInfoObjects ( void );


#endif // GAP_OBJECTS_H

/****************************************************************************
**

*E  objects.h . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
*/
