text: /**************************************************************/
  /* ********************************************************** */
  /* *                                                        * */
  /* *                       HASHING                          * */
  /* *                                                        * */
  /* *  $Module:   HASHARRAY                                  * */ 
  /* *                                                        * */
  /* *  Copyright (C) 1997, 1998, 1999, 2000, 2001            * */
  /* *  MPI fuer Informatik                                   * */
  /* *                                                        * */
  /* *  This program is free software; you can redistribute   * */
  /* *  it and/or modify it under the terms of the GNU        * */
  /* *  General Public License as published by the Free       * */
  /* *  Software Foundation; either version 2 of the License, * */
  /* *  or (at your option) any later version.                * */
  /* *                                                        * */
  /* *  This program is distributed in the hope that it will  * */
  /* *  be useful, but WITHOUT ANY WARRANTY; without even     * */
  /* *  the implied warranty of MERCHANTABILITY or FITNESS    * */
  /* *  FOR A PARTICULAR PURPOSE.  See the GNU General Public * */
  /* *  License for more details.                             * */
  /* *                                                        * */
  /* *  You should have received a copy of the GNU General    * */
  /* *  Public License along with this program; if not, write * */
  /* *  to the Free Software Foundation, Inc., 59 Temple      * */
  /* *  Place, Suite 330, Boston, MA  02111-1307  USA         * */
  /* *                                                        * */
  /* *                                                        * */
  /* $Revision$                                        * */
  /* $State$                                            * */
  /* $Date$                             * */
  /* $Author$                                       * */
  /* *                                                        * */
  /* *             Contact:                                   * */
  /* *             Christoph Weidenbach                       * */
  /* *             MPI fuer Informatik                        * */
  /* *             Stuhlsatzenhausweg 85                      * */
  /* *             66123 Saarbruecken                         * */
  /* *             Email: weidenb@mpi-sb.mpg.de               * */
  /* *             Germany                                    * */
  /* *                                                        * */
  /* ********************************************************** */
  /**************************************************************/
  
  
  /* $RCSfile$ */
  
  #ifndef _HASHARRAY_
  #define _HASHARRAY_
  
  /**************************************************************/
  /* Includes                                                   */
  /**************************************************************/
  
  #include "list.h"
  
  /**************************************************************/
  /* Structures                                                 */
  /**************************************************************/
  
  #define hsh__SIZE 29            /* a prime */
  
  /* Each Entry is a list of pairs <key,list of values> */
  
  typedef LIST* HASH;
  
  void hsh_Check(HASH H);
  
  /**************************************************************/
  /* Inline Functions                                           */
  /**************************************************************/
  
  static __inline__ unsigned long hsh_Index(POINTER Key)
  /**************************************************************
    INPUT:   A pointer
    RETURNS: A key for the hasharray
  ***************************************************************/
  {
    return (unsigned long)Key % hsh__SIZE;
  }
  
  static __inline__ void hsh_Put(HASH H, POINTER Key, POINTER Value)
  /**************************************************************
    INPUT:   A hasharray, a pointer used as key and a pointer to a data item
    EFFECT:  Add Value to the list of data items associated with the key,
             if it isn't a member already
  ***************************************************************/
  {
    LIST Scan, Pair;
    unsigned long HashKey;
    HashKey = hsh_Index(Key);
    for (Scan = H[HashKey]; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      Pair = list_Car(Scan);
      if (list_PairFirst(Pair) == Key) {
        if (!list_PointerMember(list_PairSecond(Pair), Value))
  	list_Rplacd(Pair, list_Cons(Value, list_PairSecond(Pair)));
  #ifdef CHECK
        hsh_Check(H);
  #endif
        return;
      }
    }
    H[HashKey] = list_Cons(list_PairCreate(Key, list_List(Value)), H[HashKey]);
  #ifdef CHECK
    hsh_Check(H);
  #endif
  }
  
  static __inline__ void hsh_PutList(HASH H, POINTER Key, LIST List)
  /**************************************************************
    INPUT:   A hasharray, a pointer used as key and a list of data items
    EFFECT:  Add the list to the list of data items associated with the key,
             and delete all duplicates.
  ***************************************************************/
  {
    LIST Scan, Pair;
    unsigned long HashKey;
  
    HashKey = hsh_Index(Key);
    for (Scan = H[HashKey]; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      Pair = list_Car(Scan);
      if (list_PairFirst(Pair) == Key) {
        list_Rplacd(Pair, list_Nconc(list_PairSecond(Pair), List));
  #ifdef CHECK
        hsh_Check(H);
  #endif
        return;
      }
    }
    H[HashKey] = list_Cons(list_PairCreate(Key, List), H[HashKey]);
  #ifdef CHECK
    hsh_Check(H);
  #endif
  }
  
  static __inline__ void hsh_PutListWithCompareFunc(HASH H, POINTER Key, 
  						  LIST List,
  						  BOOL (*Test)(POINTER, POINTER), 
  						  unsigned long (*HashFunc)(POINTER))
  /**************************************************************
    INPUT:   A hasharray, a pointer used as key, a list of data
             items, a test function for key equality and a
  	   hashing function.
    EFFECT:  Add the list to the list of data items associated
             with the key, and delete all duplicates.
  ***************************************************************/
  {
    LIST Scan, Pair;
    unsigned long HashKey;
  
    HashKey = (unsigned long) HashFunc(Key);
    for (Scan = H[HashKey]; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      Pair = (LIST) list_Car(Scan);
      if (Test(list_PairFirst(Pair), Key)) {
        list_Rplacd(Pair, list_Nconc(list_PairSecond(Pair), List));
  #ifdef CHECK
        hsh_Check(H);
  #endif
        return;
      }
    }
    H[HashKey] = list_Cons(list_PairCreate(Key, List), H[HashKey]);
  #ifdef CHECK
    hsh_Check(H);
  #endif
  }
  
  static __inline__ LIST hsh_Get(HASH H, POINTER Key)
  /**************************************************************
    INPUT:   A hasharray and a pointer used as key
    RETURNS: The list of data items associated with the key
  ***************************************************************/
  {
    LIST Scan, Pair;
  
    for (Scan = H[hsh_Index(Key)]; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      Pair = list_Car(Scan);
      if (list_PairFirst(Pair) == Key)
        return list_PairSecond(Pair);
    }
    return NULL;
  }
  
  static __inline__ void hsh_DelItem(HASH H, POINTER Key)
  /**************************************************************
    INPUT:   A hasharray and a pointer used as key
    RETURNS: The information associated with the key is deleted
  ***************************************************************/
  {
    LIST Scan, Pair;
    unsigned long k;
  
    k = hsh_Index(Key);
    for (Scan = H[k]; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      Pair = list_Car(Scan);
      if (list_PairFirst(Pair) == Key) {
        list_Delete(list_PairSecond(Pair));
        list_PairFree(Pair);
        H[k] = list_PointerDeleteElement(H[k], Pair);
        return;
      }
    }
  }
  
  static __inline__ LIST hsh_GetWithCompareFunc(HASH H, POINTER Key,
  					      BOOL (*Test)(POINTER, POINTER),
  					      unsigned long (*HashFunc)(POINTER))
  /**************************************************************
    INPUT:   A hasharray, a pointer used as key, a compare function
             for keys and a hash function for keys.
    RETURNS: The list of data items associated with the key
  ***************************************************************/
  {
    LIST Scan, Pair;
  
    for (Scan = H[HashFunc(Key)]; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      Pair = list_Car(Scan);
      if (Test(list_PairFirst(Pair), Key))
        return list_PairSecond(Pair);
    }
    return NULL;
  }
  
  
  static __inline__ unsigned long hsh_StringHashKey(const char* Label)
  {
    unsigned long i, s;
    s = 0;
    for (i = 0; i <= strlen(Label); i++)
      s += Label[i];
    s = s % hsh__SIZE;
    return s;
  }
  
  /**************************************************************/
  /* Functions                                                  */
  /**************************************************************/
  
  HASH hsh_Create(void);
  void hsh_Reset(HASH H);
  void hsh_Delete(HASH H);
  LIST hsh_GetAllEntries(HASH H);
  
  #endif
  
  
  