/****************************************************************************
**
*W  opers.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 declares the functions of the  filters, operations, attributes,
**  and properties package.
*/

#ifndef libGAP_GAP_OPERS_H
#define libGAP_GAP_OPERS_H


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

*V  TRY_NEXT_METHOD . . . . . . . . . . . . . . . . . `TRY_NEXT_MESSAGE' flag
*/
extern libGAP_Obj libGAP_TRY_NEXT_METHOD;


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

*F  IS_OPERATION( <obj> ) . . . . . . . . . . check if object is an operation
*/
#define libGAP_IS_OPERATION(func) \
    (libGAP_TNUM_OBJ(func) == libGAP_T_FUNCTION && libGAP_SIZE_OBJ(func) == libGAP_SIZE_OPER )

/****************************************************************************
**
*F  FLAG1_FILT( <oper> )  . . . . . . . . . .  flag 1 list of an `and' filter
*/
#define libGAP_FLAG1_FILT(oper)        (*            (libGAP_ADDR_OBJ(oper) +16     ) )


/****************************************************************************
**
*F  FLAG2_FILT( <oper> )  . . . . . . . . . .  flag 2 list of an `and' filter
*/
#define libGAP_FLAG2_FILT(oper)        (*            (libGAP_ADDR_OBJ(oper) +17     ) )


/****************************************************************************
**
*F  FLAGS_FILT( <oper> )  . . . . . . . . . . . . . . . . . flags of a filter
*/
#define libGAP_FLAGS_FILT(oper)        (*            (libGAP_ADDR_OBJ(oper) +18     ) )


/****************************************************************************
**
*F  SETTER_FILT( <oper> ) . . . . . . . . . . . . . . . .  setter of a filter
*/
#define libGAP_SETTR_FILT(oper)        (*            (libGAP_ADDR_OBJ(oper) +19     ) )


/****************************************************************************
**
*F  TESTR_FILT( <oper> )  . . . . . . . . . . . . . . . .  tester of a filter
*/
#define libGAP_TESTR_FILT(oper)        (*            (libGAP_ADDR_OBJ(oper) +20     ) )


/****************************************************************************
**
*F  METHS_OPER( <oper> )  . . . . . . . . . . . . method list of an operation
*/
#define libGAP_METHS_OPER(oper,i)      (*            (libGAP_ADDR_OBJ(oper) +21+ (i)) )


/****************************************************************************
**
*F  CACHE_OPER( <oper> )  . . . . . . . . . . . . . . . cache of an operation
*/
#define libGAP_CACHE_OPER(oper,i)      (*            (libGAP_ADDR_OBJ(oper) +29+ (i)) )

/****************************************************************************
**
*F  ENABLED_ATTR( <oper> ) . . . . true if the operation is an attribute and
**                                 storing is enabled (default) else false
*/

#define libGAP_ENABLED_ATTR(oper)                    ((libGAP_UInt)(libGAP_ADDR_OBJ(oper)[37])) 

/****************************************************************************
**
*F  SET_ENABLED_ATTR( <oper>, <new> )  . set a new value that records whether 
**                                       storing is enabled for an operation
*/

#define libGAP_SET_ENABLED_ATTR(oper, new)       ((libGAP_ADDR_OBJ(oper)[37]) = (libGAP_Obj)(new)) 

/****************************************************************************
**
*V  SIZE_OPER . . . . . . . . . . . . . . . . . . . . .  size of an operation
*/
#define libGAP_SIZE_OPER               (38*sizeof(libGAP_Bag))


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

*F * * * * * * * * * * * * internal flags functions * * * * * * * * * * * * *
*/


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

*F  NEW_FLAGS( <flags>, <size> )  . . . . . . . . . . . . . .  new flags list
*/
#define libGAP_NEW_FLAGS( flags, size ) \
    ( flags = libGAP_NewBag( libGAP_T_FLAGS, libGAP_SIZE_PLEN_FLAGS(size) ) )


/****************************************************************************
**
*F  SIZE_PLEN_FLAGS( <plen> ) . .  size for a flags list with physical length
*/
#define libGAP_SIZE_PLEN_FLAGS(plen) \
  (4*sizeof(libGAP_Obj)+((plen)+libGAP_BIPEB-1)/libGAP_BIPEB*sizeof(libGAP_Obj))



/****************************************************************************
**
*F  TRUES_FLAGS( <flags> )  . . . . . . . . . . list of trues of a flags list
**
**  returns the list of trues of <flags> or 0 if the list is not known yet.
*/
#define libGAP_TRUES_FLAGS(flags)              (libGAP_ADDR_OBJ(flags)[0])


/****************************************************************************
**
*F  SET_TRUES_FLAGS( <flags>, <trues> ) . set number of trues of a flags list
*/
#define libGAP_SET_TRUES_FLAGS(flags,trues)    (libGAP_ADDR_OBJ(flags)[0] = trues)


/****************************************************************************
**
*F  HASH_FLAGS( <flags> ) . . . . . . . . . . . .  hash value of <flags> or 0
*/
#define libGAP_HASH_FLAGS(flags)               (libGAP_ADDR_OBJ(flags)[1])


/****************************************************************************
**
*F  SET_HASH_FLAGS( <flags>, <hash> ) . . . . . . . . . . . . . . .  set hash
*/
#define libGAP_SET_HASH_FLAGS(flags,hash)      (libGAP_ADDR_OBJ(flags)[1] = hash)


/****************************************************************************
**
*F  LEN_FLAGS( <flags> )  . . . . . . . . . . . . . .  length of a flags list
*/
#define libGAP_LEN_FLAGS(list)                 (libGAP_INT_INTOBJ(libGAP_ADDR_OBJ(list)[2]))


/****************************************************************************
**
*F  SET_LEN_FLAGS( <flags>, <len> ) . . . . .  set the length of a flags list
*/
#define libGAP_SET_LEN_FLAGS(flags,len)        (libGAP_ADDR_OBJ(flags)[2]=libGAP_INTOBJ_INT(len))


/****************************************************************************
**
*F  AND_CACHE_FLAGS( <flags> )  . . . . . . . . . `and' cache of a flags list
*/
#define libGAP_AND_CACHE_FLAGS(list)           (libGAP_ADDR_OBJ(list)[3])


/****************************************************************************
**
*F  SET_AND_CACHE_FLAGS( <flags>, <len> ) set the `and' cache of a flags list
*/
#define libGAP_SET_AND_CACHE_FLAGS(flags,andc)  (libGAP_ADDR_OBJ(flags)[3]=(andc))


/****************************************************************************
**
*F  NRB_FLAGS( <flags> )  . . . . . .  number of basic blocks of a flags lits
*/
#define libGAP_NRB_FLAGS(flags)                ((libGAP_LEN_FLAGS(flags)+libGAP_BIPEB-1)/libGAP_BIPEB)



/****************************************************************************
**
*F  BLOCKS_FLAGS( <flags> ) . . . . . . . . . . . . data area of a flags list
*/
#define libGAP_BLOCKS_FLAGS(flags)             ((libGAP_UInt*)(libGAP_ADDR_OBJ(flags)+4))


/****************************************************************************
**
*F  BLOCK_ELM_FLAGS( <list>, <pos> )  . . . . . . . .  block  of a flags list
**
**  'BLOCK_ELM_FLAGS' return the block containing the <pos>-th element of the
**  flags list <list> as a UInt value, which is also a  valid left hand side.
**  <pos>  must be a positive  integer  less than or  equal  to the length of
**  <list>.
**
**  Note that 'BLOCK_ELM_FLAGS' is a macro, so do not call it  with arguments
**  that have side effects.
*/
#define libGAP_BLOCK_ELM_FLAGS(list, pos)      (libGAP_BLOCKS_FLAGS(list)[((pos)-1)/libGAP_BIPEB])


/****************************************************************************
**
*F  MASK_POS_FLAGS( <pos> ) . . .  . .  bit mask for position of a flags list
**
**  MASK_POS_FLAGS(<pos>) returns  a UInt with a  single set  bit in position
**  (pos-1) % BIPEB, useful for accessing the pos'th element of a FLAGS
**
**  Note that 'MASK_POS_FLAGS'  is a macro, so  do not call it with arguments
**  that have side effects.
*/
#define libGAP_MASK_POS_FLAGS(pos)             (((libGAP_UInt) 1)<<((pos)-1)%libGAP_BIPEB)


/****************************************************************************
**
*F  ELM_FLAGS( <list>, <pos> )  . . . . . . . . . . . element of a flags list
**
**  'ELM_FLAGS' return the <pos>-th element of the flags list <list>, which
**  is either 'true' or 'false'.  <pos> must  be a positive integer less than
**  or equal to the length of <hdList>.
**
**  Note that 'ELM_FLAGS' is a macro, so do not call it  with arguments  that
**  have side effects.
*/
#define libGAP_ELM_FLAGS(list,pos) \
  ((libGAP_BLOCK_ELM_FLAGS(list,pos) & libGAP_MASK_POS_FLAGS(pos)) ?  libGAP_True : libGAP_False)


/****************************************************************************
**
*F  SET_ELM_FLAGS( <list>, <pos>, <val> ) . .  set an element of a flags list
**
**  'SET_ELM_FLAGS' sets  the element at position <pos>   in the flags list
**  <list> to the value <val>.  <pos> must be a positive integer less than or
**  equal to the length of <hdList>.  <val> must be either 'true' or 'false'.
**
**  Note that  'SET_ELM_FLAGS' is  a macro, so do not  call it with arguments
**  that have side effects.
*/
#define libGAP_SET_ELM_FLAGS(list,pos,val)  \
 ((val) == libGAP_True ? \
  (libGAP_BLOCK_ELM_FLAGS(list, pos) |= libGAP_MASK_POS_FLAGS(pos)) : \
  (libGAP_BLOCK_ELM_FLAGS(list, pos) &= ~libGAP_MASK_POS_FLAGS(pos)))

/****************************************************************************
**
*F  FuncIS_SUBSET_FLAGS( <self>, <flags1>, <flags2> ) . . . . . . subset test
*/

extern libGAP_Obj libGAP_FuncIS_SUBSET_FLAGS( libGAP_Obj self, libGAP_Obj flags1, libGAP_Obj flags2 );
     
/****************************************************************************
**

*F * * * * * * * * * * *  internal filter functions * * * * * * * * * * * * *
*/


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

*V  CountFlags  . . . . . . . . . . . . . . . . . . . . next free flag number
*/
extern libGAP_Int libGAP_CountFlags;


/****************************************************************************
**
*V  SET_FILTER_OBJ  . . . . . . . . . . . .  library function to set a filter
*/
extern libGAP_Obj libGAP_SET_FILTER_OBJ;


/****************************************************************************
**
*V  RESET_FILTER_OBJ  . . . . . . . . . .  library function to reset a filter
*/
extern libGAP_Obj libGAP_RESET_FILTER_OBJ;



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

*F  SetterFilter( <oper> )  . . . . . . . . . . . . . . .  setter of a filter
*/
extern libGAP_Obj libGAP_SetterFilter (
    libGAP_Obj                 oper );


/****************************************************************************
**
*F  SetterAndFilter( <getter> )  . . . . . .  setter of a concatenated filter
*/
extern libGAP_Obj libGAP_DoSetAndFilter (
    libGAP_Obj                 self,
    libGAP_Obj                 obj,
    libGAP_Obj                 val );

extern libGAP_Obj libGAP_SetterAndFilter (
    libGAP_Obj                 getter );
        

/****************************************************************************
**
*F  TesterFilter( <oper> )  . . . . . . . . . . . . . . .  tester of a filter
*/
extern libGAP_Obj libGAP_TesterFilter (
    libGAP_Obj                 oper );


/****************************************************************************
**
*F  TestAndFilter( <getter> )  . . . . . . . .tester of a concatenated filter
*/
extern libGAP_Obj libGAP_DoTestAndFilter (
    libGAP_Obj                 self,
    libGAP_Obj                 obj );

extern libGAP_Obj libGAP_TesterAndFilter (
    libGAP_Obj                 getter );


/****************************************************************************
**
*F  NewFilter( <name>, <narg>, <nams>, <hdlr> )  . . . . .  make a new filter
*/
extern libGAP_Obj libGAP_DoTestFilter (
    libGAP_Obj                 self,
    libGAP_Obj                 obj );

extern libGAP_Obj libGAP_NewTesterFilter (
    libGAP_Obj                 getter );

extern libGAP_Obj libGAP_DoSetFilter (
    libGAP_Obj                 self,
    libGAP_Obj                 obj,
    libGAP_Obj                 val );

extern libGAP_Obj libGAP_NewSetterFilter (
    libGAP_Obj                 getter );

extern libGAP_Obj libGAP_DoFilter (
    libGAP_Obj                 self,
    libGAP_Obj                 obj );

extern libGAP_Obj libGAP_NewFilter (
    libGAP_Obj                 name,
    libGAP_Int                 narg,
    libGAP_Obj                 nams,
    libGAP_ObjFunc             hdlr );


extern libGAP_Obj libGAP_DoTestAttribute( libGAP_Obj self, libGAP_Obj obj);

/****************************************************************************
**
*F  NewAndFilter( <filt1>, <filt2> ) . . . . . make a new concatenated filter
*/
extern libGAP_Obj libGAP_DoAndFilter (
    libGAP_Obj                 self,
    libGAP_Obj                 obj );

extern libGAP_Obj libGAP_NewAndFilter (
    libGAP_Obj                 oper1,
    libGAP_Obj                 oper2 );


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

*V  ReturnTrueFilter . . . . . . . . . . . . . . . . the return 'true' filter
*/
extern libGAP_Obj libGAP_ReturnTrueFilter;


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

*F * * * * * * * * * *  internal operation functions  * * * * * * * * * * * *
*/


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

*F  NewOperation( <name> )  . . . . . . . . . . . . . .  make a new operation
*/
extern libGAP_Obj libGAP_DoOperation0Args (
            libGAP_Obj                 oper );

extern libGAP_Obj libGAP_DoOperation1Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1 );

extern libGAP_Obj libGAP_DoOperation2Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2 );

extern libGAP_Obj libGAP_DoOperation3Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3 );

extern libGAP_Obj libGAP_DoOperation4Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3,
            libGAP_Obj                 arg4 );

extern libGAP_Obj libGAP_DoOperation5Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3,
            libGAP_Obj                 arg4,
            libGAP_Obj                 arg5 );

extern libGAP_Obj libGAP_DoOperation6Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3,
            libGAP_Obj                 arg4,
            libGAP_Obj                 arg5,
            libGAP_Obj                 arg6 );

extern libGAP_Obj libGAP_DoOperationXArgs (
            libGAP_Obj                 self,
            libGAP_Obj                 args );

extern libGAP_Obj libGAP_DoVerboseOperation0Args (
            libGAP_Obj                 oper );

extern libGAP_Obj libGAP_DoVerboseOperation1Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1 );

extern libGAP_Obj libGAP_DoVerboseOperation2Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2 );

extern libGAP_Obj libGAP_DoVerboseOperation3Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3 );

extern libGAP_Obj libGAP_DoVerboseOperation4Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3,
            libGAP_Obj                 arg4 );

extern libGAP_Obj libGAP_DoVerboseOperation5Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3,
            libGAP_Obj                 arg4,
            libGAP_Obj                 arg5 );

extern libGAP_Obj libGAP_DoVerboseOperation6Args (
            libGAP_Obj                 oper,
            libGAP_Obj                 arg1,
            libGAP_Obj                 arg2,
            libGAP_Obj                 arg3,
            libGAP_Obj                 arg4,
            libGAP_Obj                 arg5,
            libGAP_Obj                 arg6 );

extern libGAP_Obj libGAP_DoVerboseOperationXArgs (
            libGAP_Obj                 self,
            libGAP_Obj                 args );

extern libGAP_Obj libGAP_NewOperation (
            libGAP_Obj                 name,
            libGAP_Int                 narg,
            libGAP_Obj                 nams,
            libGAP_ObjFunc             hdlr );


/****************************************************************************
**
*F  NewAttribute( <name> )  . . . . . . . . . . . . . .  make a new attribute
*/
extern  libGAP_Obj libGAP_DoAttribute (
            libGAP_Obj                 self,
            libGAP_Obj                 obj );

extern  libGAP_Obj libGAP_DoVerboseAttribute (
            libGAP_Obj                 self,
            libGAP_Obj                 obj );

extern  libGAP_Obj libGAP_NewAttribute (
            libGAP_Obj                 name,
            libGAP_Int                 narg,
            libGAP_Obj                 nams,
            libGAP_ObjFunc             hdlr );

/****************************************************************************
**
*F  NewProperty( <name> ) . . . . . . . . . . . . . . . . make a new property
*/
extern libGAP_Obj libGAP_DoProperty (
            libGAP_Obj                 self,
            libGAP_Obj                 obj );

extern libGAP_Obj libGAP_NewProperty (
            libGAP_Obj                 name,
            libGAP_Int                 narg,
            libGAP_Obj                 nams,
            libGAP_ObjFunc             hdlr );

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

*F  InstallMethodArgs( <oper>, <func> ) . . . . . . . . . . .  clone function
**
**  There is a problem  with uncompleted functions: if  they are  cloned then
**  only   the orignal and not  the  clone will be  completed.  Therefore the
**  clone must postpone the real cloning.
*/
extern void libGAP_InstallMethodArgs (
    libGAP_Obj                 oper,
    libGAP_Obj                 func );


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

*F  ChangeDoOperations( <oper>, <verb> )
*/
extern void libGAP_ChangeDoOperations (
            libGAP_Obj                 oper,
            libGAP_Int                 verb );

/****************************************************************************
**
*F  SaveOperationExtras( <oper> ) . . .  additional savng for functions which
**                                       are operations
**
**  This is called by SaveFunction when the function bag is too large to be
**  a simple function, and so must be an operation
**
*/

extern void libGAP_SaveOperationExtras( libGAP_Obj oper );

/****************************************************************************
**
*F  LoadOperationExtras( <oper> ) . .  additional loading for functions which
**                                       are operations
**
**  This is called by LoadFunction when the function bag is too large to be
**  a simple function, and so must be an operation
**
*/

extern void libGAP_LoadOperationExtras( libGAP_Obj oper );


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

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


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

*F  InitInfoOpers() . . . . . . . . . . . . . . . . . table of init functions
*/
libGAP_StructInitInfo * libGAP_InitInfoOpers ( void );


#endif // GAP_OPERS_H

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

*E  opers.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
*/
