
(********************************************************************)
(*                                                                  *)
(*  chkhsh.sd7    Checks hash table operations                      *)
(*  Copyright (C) 2009  Thomas Mertes                               *)
(*                                                                  *)
(*  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., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


$ include "seed7_05.s7i";
  include "stdio.s7i";
  include "bigint.s7i";
  include "float.s7i";
  include "complex.s7i";

enable_output(type);

const type: booleanBooleanHash    is hash [boolean] boolean;
const type: booleanIntegerHash    is hash [boolean] integer;
const type: booleanBigIntegerHash is hash [boolean] bigInteger;
const type: booleanFloatHash      is hash [boolean] float;
const type: booleanComplexHash    is hash [boolean] complex;
const type: booleanCharHash       is hash [boolean] char;
const type: booleanStringHash     is hash [boolean] string;
const type: booleanTypeHash       is hash [boolean] type;
const type: booleanReferenceHash  is hash [boolean] reference;
const type: booleanHashHash       is hash [boolean] booleanBooleanHash;

const type: integerBooleanHash    is hash [integer] boolean;
const type: integerIntegerHash    is hash [integer] integer;
const type: integerBigIntegerHash is hash [integer] bigInteger;
const type: integerFloatHash      is hash [integer] float;
const type: integerComplexHash    is hash [integer] complex;
const type: integerCharHash       is hash [integer] char;
const type: integerStringHash     is hash [integer] string;
const type: integerTypeHash       is hash [integer] type;
const type: integerReferenceHash  is hash [integer] reference;
const type: integerHashHash       is hash [integer] integerBooleanHash;

const type: floatBooleanHash      is hash [float] boolean;
const type: floatIntegerHash      is hash [float] integer;
const type: floatBigIntegerHash   is hash [float] bigInteger;
const type: floatFloatHash        is hash [float] float;
const type: floatComplexHash      is hash [float] complex;
const type: floatCharHash         is hash [float] char;
const type: floatStringHash       is hash [float] string;
const type: floatTypeHash         is hash [float] type;
const type: floatReferenceHash    is hash [float] reference;
const type: floatHashHash         is hash [float] floatBooleanHash;

const type: complexBooleanHash    is hash [complex] boolean;
const type: complexIntegerHash    is hash [complex] integer;
const type: complexBigIntegerHash is hash [complex] bigInteger;
const type: complexFloatHash      is hash [complex] float;
const type: complexComplexHash    is hash [complex] complex;
const type: complexCharHash       is hash [complex] char;
const type: complexStringHash     is hash [complex] string;
const type: complexTypeHash       is hash [complex] type;
const type: complexReferenceHash  is hash [complex] reference;
const type: complexHashHash       is hash [complex] complexBooleanHash;

const type: stringBooleanHash     is hash [string] boolean;
const type: stringIntegerHash     is hash [string] integer;
const type: stringBigIntegerHash  is hash [string] bigInteger;
const type: stringFloatHash       is hash [string] float;
const type: stringComplexHash     is hash [string] complex;
const type: stringCharHash        is hash [string] char;
const type: stringStringHash      is hash [string] string;
const type: stringTypeHash        is hash [string] type;
const type: stringReferenceHash   is hash [string] reference;
const type: stringHashHash        is hash [string] stringBooleanHash;


const proc: chkBooleanHash is func
  local
    var boolean: okay is TRUE;
    var booleanBooleanHash:    booleanBooleanHashVar    is booleanBooleanHash   .EMPTY_HASH;
    var booleanIntegerHash:    booleanIntegerHashVar    is booleanIntegerHash   .EMPTY_HASH;
    var booleanBigIntegerHash: booleanBigIntegerHashVar is booleanBigIntegerHash.EMPTY_HASH;
    var booleanFloatHash:      booleanFloatHashVar      is booleanFloatHash     .EMPTY_HASH;
    var booleanComplexHash:    booleanComplexHashVar    is booleanComplexHash   .EMPTY_HASH;
    var booleanCharHash:       booleanCharHashVar       is booleanCharHash      .EMPTY_HASH;
    var booleanStringHash:     booleanStringHashVar     is booleanStringHash    .EMPTY_HASH;
    var booleanTypeHash:       booleanTypeHashVar       is booleanTypeHash      .EMPTY_HASH;
    var booleanReferenceHash:  booleanReferenceHashVar  is booleanReferenceHash .EMPTY_HASH;
    var booleanHashHash:       booleanHashHashVar       is booleanHashHash      .EMPTY_HASH;
  begin
    if  length(booleanBooleanHashVar)    <> 0 or
        length(booleanIntegerHashVar)    <> 0 or
        length(booleanBigIntegerHashVar) <> 0 or
        length(booleanFloatHashVar)      <> 0 or
        length(booleanComplexHashVar)    <> 0 or
        length(booleanCharHashVar)       <> 0 or
        length(booleanStringHashVar)     <> 0 or
        length(booleanTypeHashVar)       <> 0 or
        length(booleanReferenceHashVar)  <> 0 or
        length(booleanHashHashVar)       <> 0 then
      writeln(" ***** Number of elements in empty hash[boolean] table not 0");
      okay := FALSE;
    end if;
    if  TRUE in booleanBooleanHashVar    or
        TRUE in booleanIntegerHashVar    or
        TRUE in booleanBigIntegerHashVar or
        TRUE in booleanFloatHashVar      or
        TRUE in booleanComplexHashVar    or
        TRUE in booleanCharHashVar       or
        TRUE in booleanStringHashVar     or
        TRUE in booleanTypeHashVar       or
        TRUE in booleanReferenceHashVar  or
        TRUE in booleanHashHashVar       then
      writeln(" ***** Elements found in empty hash table");
      okay := FALSE;
    end if;
    booleanBooleanHashVar    @:= [TRUE] TRUE;
    booleanIntegerHashVar    @:= [TRUE] 1234;
    booleanBigIntegerHashVar @:= [TRUE] 9999999999_;
    booleanFloatHashVar      @:= [TRUE] 3.1415926535;
    booleanComplexHashVar    @:= [TRUE] complex(1.2, 3.4);
    booleanCharHashVar       @:= [TRUE] 'Q';
    booleanStringHashVar     @:= [TRUE] "success";
    booleanTypeHashVar       @:= [TRUE] char;
    booleanReferenceHashVar  @:= [TRUE] NIL;
    booleanHashHashVar       @:= [TRUE] booleanBooleanHashVar;
    if  length(booleanBooleanHashVar)    <> 1 or
        length(booleanIntegerHashVar)    <> 1 or
        length(booleanBigIntegerHashVar) <> 1 or
        length(booleanFloatHashVar)      <> 1 or
        length(booleanComplexHashVar)    <> 1 or
        length(booleanCharHashVar)       <> 1 or
        length(booleanStringHashVar)     <> 1 or
        length(booleanTypeHashVar)       <> 1 or
        length(booleanReferenceHashVar)  <> 1 or
        length(booleanHashHashVar)       <> 1 then
      writeln(" ***** Number of elements in hash[boolean] table not 1");
      okay := FALSE;
    end if;
    if  TRUE in booleanBooleanHashVar    and
        TRUE in booleanIntegerHashVar    and
        TRUE in booleanBigIntegerHashVar and
        TRUE in booleanFloatHashVar      and
        TRUE in booleanComplexHashVar    and
        TRUE in booleanCharHashVar       and
        TRUE in booleanStringHashVar     and
        TRUE in booleanTypeHashVar       and
        TRUE in booleanReferenceHashVar  and
        TRUE in booleanHashHashVar       then
      noop;
    else
      writeln(" ***** Elements missing in hash[boolean] table");
      okay := FALSE;
    end if;
    booleanBooleanHashVar    @:= [TRUE] TRUE;
    booleanIntegerHashVar    @:= [TRUE] 1234;
    booleanBigIntegerHashVar @:= [TRUE] 9999999999_;
    booleanFloatHashVar      @:= [TRUE] 3.1415926535;
    booleanComplexHashVar    @:= [TRUE] complex(1.2, 3.4);
    booleanCharHashVar       @:= [TRUE] 'Q';
    booleanStringHashVar     @:= [TRUE] "success";
    booleanTypeHashVar       @:= [TRUE] char;
    booleanReferenceHashVar  @:= [TRUE] NIL;
    booleanHashHashVar       @:= [TRUE] booleanBooleanHashVar;
    if  TRUE not in booleanBooleanHashVar    or
        TRUE not in booleanIntegerHashVar    or
        TRUE not in booleanBigIntegerHashVar or
        TRUE not in booleanFloatHashVar      or
        TRUE not in booleanComplexHashVar    or
        TRUE not in booleanCharHashVar       or
        TRUE not in booleanStringHashVar     or
        TRUE not in booleanTypeHashVar       or
        TRUE not in booleanReferenceHashVar  or
        TRUE not in booleanHashHashVar       then
      writeln(" ***** Elements missing in hash[boolean] table");
      okay := FALSE;
    end if;
    if  booleanBooleanHashVar    [TRUE] <> TRUE              or
        booleanIntegerHashVar    [TRUE] <> 1234              or
        booleanBigIntegerHashVar [TRUE] <> 9999999999_       or
        booleanFloatHashVar      [TRUE] <> 3.1415926535      or
        booleanComplexHashVar    [TRUE] <> complex(1.2, 3.4) or
        booleanCharHashVar       [TRUE] <> 'Q'               or
        booleanStringHashVar     [TRUE] <> "success"         or
        booleanTypeHashVar       [TRUE] <> char              or
        booleanReferenceHashVar  [TRUE] <> NIL               then
      writeln(" ***** Elements with wrong value in hash[boolean] table");
      okay := FALSE;
    end if;
    if okay then
      writeln("Hash tables with boolean keys work correct.");
    else
      writeln(" ***** Hash tables with boolean keys do not work correct");
      writeln;
    end if;
  end func;

const proc: chkIntegerHash is func
  local
    var boolean: okay is TRUE;
    var integerBooleanHash:    integerBooleanHashVar    is integerBooleanHash   .EMPTY_HASH;
    var integerIntegerHash:    integerIntegerHashVar    is integerIntegerHash   .EMPTY_HASH;
    var integerBigIntegerHash: integerBigIntegerHashVar is integerBigIntegerHash.EMPTY_HASH;
    var integerFloatHash:      integerFloatHashVar      is integerFloatHash     .EMPTY_HASH;
    var integerComplexHash:    integerComplexHashVar    is integerComplexHash   .EMPTY_HASH;
    var integerCharHash:       integerCharHashVar       is integerCharHash      .EMPTY_HASH;
    var integerStringHash:     integerStringHashVar     is integerStringHash    .EMPTY_HASH;
    var integerTypeHash:       integerTypeHashVar       is integerTypeHash      .EMPTY_HASH;
    var integerReferenceHash:  integerReferenceHashVar  is integerReferenceHash .EMPTY_HASH;
    var integerHashHash:       integerHashHashVar       is integerHashHash      .EMPTY_HASH;
  begin
    if  length(integerBooleanHashVar)    <> 0 or
        length(integerIntegerHashVar)    <> 0 or
        length(integerBigIntegerHashVar) <> 0 or
        length(integerFloatHashVar)      <> 0 or
        length(integerComplexHashVar)    <> 0 or
        length(integerCharHashVar)       <> 0 or
        length(integerStringHashVar)     <> 0 or
        length(integerTypeHashVar)       <> 0 or
        length(integerReferenceHashVar)  <> 0 or
        length(integerHashHashVar)       <> 0 then
      writeln(" ***** Number of elements in empty hash[integer] table not 0");
      okay := FALSE;
    end if;
    if  87654321 in integerBooleanHashVar    or
        87654321 in integerIntegerHashVar    or
        87654321 in integerBigIntegerHashVar or
        87654321 in integerFloatHashVar      or
        87654321 in integerComplexHashVar    or
        87654321 in integerCharHashVar       or
        87654321 in integerStringHashVar     or
        87654321 in integerTypeHashVar       or
        87654321 in integerReferenceHashVar  or
        87654321 in integerHashHashVar       then
      writeln(" ***** Elements found in empty hash table");
      okay := FALSE;
    end if;
    integerBooleanHashVar    @:= [87654321] TRUE;
    integerIntegerHashVar    @:= [87654321] 1234;
    integerBigIntegerHashVar @:= [87654321] 9999999999_;
    integerFloatHashVar      @:= [87654321] 3.1415926535;
    integerComplexHashVar    @:= [87654321] complex(1.2, 3.4);
    integerCharHashVar       @:= [87654321] 'Q';
    integerStringHashVar     @:= [87654321] "success";
    integerTypeHashVar       @:= [87654321] char;
    integerReferenceHashVar  @:= [87654321] NIL;
    integerHashHashVar       @:= [87654321] integerBooleanHashVar;
    if  length(integerBooleanHashVar)    <> 1 or
        length(integerIntegerHashVar)    <> 1 or
        length(integerBigIntegerHashVar) <> 1 or
        length(integerFloatHashVar)      <> 1 or
        length(integerComplexHashVar)    <> 1 or
        length(integerCharHashVar)       <> 1 or
        length(integerStringHashVar)     <> 1 or
        length(integerTypeHashVar)       <> 1 or
        length(integerReferenceHashVar)  <> 1 or
        length(integerHashHashVar)       <> 1 then
      writeln(" ***** Number of elements in hash[integer] table not 1");
      okay := FALSE;
    end if;
    if  87654321 in integerBooleanHashVar    and
        87654321 in integerIntegerHashVar    and
        87654321 in integerBigIntegerHashVar and
        87654321 in integerFloatHashVar      and
        87654321 in integerComplexHashVar    and
        87654321 in integerCharHashVar       and
        87654321 in integerStringHashVar     and
        87654321 in integerTypeHashVar       and
        87654321 in integerReferenceHashVar  and
        87654321 in integerHashHashVar       then
      noop;
    else
      writeln(" ***** Elements missing in hash[integer] table");
      okay := FALSE;
    end if;
    integerBooleanHashVar    @:= [87654321] TRUE;
    integerIntegerHashVar    @:= [87654321] 1234;
    integerBigIntegerHashVar @:= [87654321] 9999999999_;
    integerFloatHashVar      @:= [87654321] 3.1415926535;
    integerComplexHashVar    @:= [87654321] complex(1.2, 3.4);
    integerCharHashVar       @:= [87654321] 'Q';
    integerStringHashVar     @:= [87654321] "success";
    integerTypeHashVar       @:= [87654321] char;
    integerReferenceHashVar  @:= [87654321] NIL;
    integerHashHashVar       @:= [87654321] integerBooleanHashVar;
    if  87654321 not in integerBooleanHashVar    or
        87654321 not in integerIntegerHashVar    or
        87654321 not in integerBigIntegerHashVar or
        87654321 not in integerFloatHashVar      or
        87654321 not in integerComplexHashVar    or
        87654321 not in integerCharHashVar       or
        87654321 not in integerStringHashVar     or
        87654321 not in integerTypeHashVar       or
        87654321 not in integerReferenceHashVar  or
        87654321 not in integerHashHashVar       then
      writeln(" ***** Elements missing in hash[integer] table");
      okay := FALSE;
    end if;
    if  integerBooleanHashVar    [87654321] <> TRUE              or
        integerIntegerHashVar    [87654321] <> 1234              or
        integerBigIntegerHashVar [87654321] <> 9999999999_       or
        integerFloatHashVar      [87654321] <> 3.1415926535      or
        integerComplexHashVar    [87654321] <> complex(1.2, 3.4) or
        integerCharHashVar       [87654321] <> 'Q'               or
        integerStringHashVar     [87654321] <> "success"         or
        integerTypeHashVar       [87654321] <> char              or
        integerReferenceHashVar  [87654321] <> NIL               then
      writeln(" ***** Elements with wrong value in hash[integer] table");
      okay := FALSE;
    end if;
    if okay then
      writeln("Hash tables with integer keys work correct.");
    else
      writeln(" ***** Hash tables with integer keys do not work correct");
      writeln;
    end if;
  end func;


const proc: chkFloatHash is func
  local
    var boolean: okay is TRUE;
    var floatBooleanHash:    floatBooleanHashVar    is floatBooleanHash   .EMPTY_HASH;
    var floatIntegerHash:    floatIntegerHashVar    is floatIntegerHash   .EMPTY_HASH;
    var floatBigIntegerHash: floatBigIntegerHashVar is floatBigIntegerHash.EMPTY_HASH;
    var floatFloatHash:      floatFloatHashVar      is floatFloatHash     .EMPTY_HASH;
    var floatComplexHash:    floatComplexHashVar    is floatComplexHash   .EMPTY_HASH;
    var floatCharHash:       floatCharHashVar       is floatCharHash      .EMPTY_HASH;
    var floatStringHash:     floatStringHashVar     is floatStringHash    .EMPTY_HASH;
    var floatTypeHash:       floatTypeHashVar       is floatTypeHash      .EMPTY_HASH;
    var floatReferenceHash:  floatReferenceHashVar  is floatReferenceHash .EMPTY_HASH;
    var floatHashHash:       floatHashHashVar       is floatHashHash      .EMPTY_HASH;
  begin
    if  length(floatBooleanHashVar)    <> 0 or
        length(floatIntegerHashVar)    <> 0 or
        length(floatBigIntegerHashVar) <> 0 or
        length(floatFloatHashVar)      <> 0 or
        length(floatComplexHashVar)    <> 0 or
        length(floatCharHashVar)       <> 0 or
        length(floatStringHashVar)     <> 0 or
        length(floatTypeHashVar)       <> 0 or
        length(floatReferenceHashVar)  <> 0 or
        length(floatHashHashVar)       <> 0 then
      writeln(" ***** Number of elements in empty hash[float] table not 0");
      okay := FALSE;
    end if;
    if  3.1415926535 in floatBooleanHashVar    or
        3.1415926535 in floatIntegerHashVar    or
        3.1415926535 in floatBigIntegerHashVar or
        3.1415926535 in floatFloatHashVar      or
        3.1415926535 in floatComplexHashVar    or
        3.1415926535 in floatCharHashVar       or
        3.1415926535 in floatStringHashVar     or
        3.1415926535 in floatTypeHashVar       or
        3.1415926535 in floatReferenceHashVar  or
        3.1415926535 in floatHashHashVar       then
      writeln(" ***** Elements found in empty hash table");
      okay := FALSE;
    end if;
    floatBooleanHashVar    @:= [3.1415926535] TRUE;
    floatIntegerHashVar    @:= [3.1415926535] 1234;
    floatBigIntegerHashVar @:= [3.1415926535] 9999999999_;
    floatFloatHashVar      @:= [3.1415926535] 3.1415926535;
    floatComplexHashVar    @:= [3.1415926535] complex(1.2, 3.4);
    floatCharHashVar       @:= [3.1415926535] 'Q';
    floatStringHashVar     @:= [3.1415926535] "success";
    floatTypeHashVar       @:= [3.1415926535] char;
    floatReferenceHashVar  @:= [3.1415926535] NIL;
    floatHashHashVar       @:= [3.1415926535] floatBooleanHashVar;
    if  length(floatBooleanHashVar)    <> 1 or
        length(floatIntegerHashVar)    <> 1 or
        length(floatBigIntegerHashVar) <> 1 or
        length(floatFloatHashVar)      <> 1 or
        length(floatComplexHashVar)    <> 1 or
        length(floatCharHashVar)       <> 1 or
        length(floatStringHashVar)     <> 1 or
        length(floatTypeHashVar)       <> 1 or
        length(floatReferenceHashVar)  <> 1 or
        length(floatHashHashVar)       <> 1 then
      writeln(" ***** Number of elements in hash[float] table not 1");
      okay := FALSE;
    end if;
    if  3.1415926535 in floatBooleanHashVar    and
        3.1415926535 in floatIntegerHashVar    and
        3.1415926535 in floatBigIntegerHashVar and
        3.1415926535 in floatFloatHashVar      and
        3.1415926535 in floatComplexHashVar    and
        3.1415926535 in floatCharHashVar       and
        3.1415926535 in floatStringHashVar     and
        3.1415926535 in floatTypeHashVar       and
        3.1415926535 in floatReferenceHashVar  and
        3.1415926535 in floatHashHashVar       then
      noop;
    else
      writeln(" ***** Elements missing in hash[float] table");
      okay := FALSE;
    end if;
    floatBooleanHashVar    @:= [3.1415926535] TRUE;
    floatIntegerHashVar    @:= [3.1415926535] 1234;
    floatBigIntegerHashVar @:= [3.1415926535] 9999999999_;
    floatFloatHashVar      @:= [3.1415926535] 3.1415926535;
    floatComplexHashVar    @:= [3.1415926535] complex(1.2, 3.4);
    floatCharHashVar       @:= [3.1415926535] 'Q';
    floatStringHashVar     @:= [3.1415926535] "success";
    floatTypeHashVar       @:= [3.1415926535] char;
    floatReferenceHashVar  @:= [3.1415926535] NIL;
    floatHashHashVar       @:= [3.1415926535] floatBooleanHashVar;
    if  3.1415926535 not in floatBooleanHashVar    or
        3.1415926535 not in floatIntegerHashVar    or
        3.1415926535 not in floatBigIntegerHashVar or
        3.1415926535 not in floatFloatHashVar      or
        3.1415926535 not in floatComplexHashVar    or
        3.1415926535 not in floatCharHashVar       or
        3.1415926535 not in floatStringHashVar     or
        3.1415926535 not in floatTypeHashVar       or
        3.1415926535 not in floatReferenceHashVar  or
        3.1415926535 not in floatHashHashVar       then
      writeln(" ***** Elements missing in hash[float] table");
      okay := FALSE;
    end if;
    if  floatBooleanHashVar    [3.1415926535] <> TRUE              or
        floatIntegerHashVar    [3.1415926535] <> 1234              or
        floatBigIntegerHashVar [3.1415926535] <> 9999999999_       or
        floatFloatHashVar      [3.1415926535] <> 3.1415926535      or
        floatComplexHashVar    [3.1415926535] <> complex(1.2, 3.4) or
        floatCharHashVar       [3.1415926535] <> 'Q'               or
        floatStringHashVar     [3.1415926535] <> "success"         or
        floatTypeHashVar       [3.1415926535] <> char              or
        floatReferenceHashVar  [3.1415926535] <> NIL               then
      writeln(" ***** Elements with wrong value in hash[float] table");
      okay := FALSE;
    end if;
    if okay then
      writeln("Hash tables with float keys work correct.");
    else
      writeln(" ***** Hash tables with float keys do not work correct");
      writeln;
    end if;
  end func;


const proc: chkComplexHash is func
  local
    var boolean: okay is TRUE;
    var complexBooleanHash:    complexBooleanHashVar    is complexBooleanHash   .EMPTY_HASH;
    var complexIntegerHash:    complexIntegerHashVar    is complexIntegerHash   .EMPTY_HASH;
    var complexBigIntegerHash: complexBigIntegerHashVar is complexBigIntegerHash.EMPTY_HASH;
    var complexFloatHash:      complexFloatHashVar      is complexFloatHash     .EMPTY_HASH;
    var complexComplexHash:    complexComplexHashVar    is complexComplexHash   .EMPTY_HASH;
    var complexCharHash:       complexCharHashVar       is complexCharHash      .EMPTY_HASH;
    var complexStringHash:     complexStringHashVar     is complexStringHash    .EMPTY_HASH;
    var complexTypeHash:       complexTypeHashVar       is complexTypeHash      .EMPTY_HASH;
    var complexReferenceHash:  complexReferenceHashVar  is complexReferenceHash .EMPTY_HASH;
    var complexHashHash:       complexHashHashVar       is complexHashHash      .EMPTY_HASH;
  begin
    if  length(complexBooleanHashVar)    <> 0 or
        length(complexIntegerHashVar)    <> 0 or
        length(complexBigIntegerHashVar) <> 0 or
        length(complexFloatHashVar)      <> 0 or
        length(complexComplexHashVar)    <> 0 or
        length(complexCharHashVar)       <> 0 or
        length(complexStringHashVar)     <> 0 or
        length(complexTypeHashVar)       <> 0 or
        length(complexReferenceHashVar)  <> 0 or
        length(complexHashHashVar)       <> 0 then
      writeln(" ***** Number of elements in empty hash[complex] table not 0");
      okay := FALSE;
    end if;
    if  complex(5.6, 7.8) in complexBooleanHashVar    or
        complex(5.6, 7.8) in complexIntegerHashVar    or
        complex(5.6, 7.8) in complexBigIntegerHashVar or
        complex(5.6, 7.8) in complexFloatHashVar      or
        complex(5.6, 7.8) in complexComplexHashVar    or
        complex(5.6, 7.8) in complexCharHashVar       or
        complex(5.6, 7.8) in complexStringHashVar     or
        complex(5.6, 7.8) in complexTypeHashVar       or
        complex(5.6, 7.8) in complexReferenceHashVar  or
        complex(5.6, 7.8) in complexHashHashVar       then
      writeln(" ***** Elements found in empty hash table");
      okay := FALSE;
    end if;
    complexBooleanHashVar    @:= [complex(5.6, 7.8)] TRUE;
    complexIntegerHashVar    @:= [complex(5.6, 7.8)] 1234;
    complexBigIntegerHashVar @:= [complex(5.6, 7.8)] 9999999999_;
    complexFloatHashVar      @:= [complex(5.6, 7.8)] 3.1415926535;
    complexComplexHashVar    @:= [complex(5.6, 7.8)] complex(1.2, 3.4);
    complexCharHashVar       @:= [complex(5.6, 7.8)] 'Q';
    complexStringHashVar     @:= [complex(5.6, 7.8)] "success";
    complexTypeHashVar       @:= [complex(5.6, 7.8)] char;
    complexReferenceHashVar  @:= [complex(5.6, 7.8)] NIL;
    complexHashHashVar       @:= [complex(5.6, 7.8)] complexBooleanHashVar;
    if  length(complexBooleanHashVar)    <> 1 or
        length(complexIntegerHashVar)    <> 1 or
        length(complexBigIntegerHashVar) <> 1 or
        length(complexFloatHashVar)      <> 1 or
        length(complexComplexHashVar)    <> 1 or
        length(complexCharHashVar)       <> 1 or
        length(complexStringHashVar)     <> 1 or
        length(complexTypeHashVar)       <> 1 or
        length(complexReferenceHashVar)  <> 1 or
        length(complexHashHashVar)       <> 1 then
      writeln(" ***** Number of elements in hash[complex] table not 1");
      okay := FALSE;
    end if;
    if  complex(5.6, 7.8) in complexBooleanHashVar    and
        complex(5.6, 7.8) in complexIntegerHashVar    and
        complex(5.6, 7.8) in complexBigIntegerHashVar and
        complex(5.6, 7.8) in complexFloatHashVar      and
        complex(5.6, 7.8) in complexComplexHashVar    and
        complex(5.6, 7.8) in complexCharHashVar       and
        complex(5.6, 7.8) in complexStringHashVar     and
        complex(5.6, 7.8) in complexTypeHashVar       and
        complex(5.6, 7.8) in complexReferenceHashVar  and
        complex(5.6, 7.8) in complexHashHashVar       then
      noop;
    else
      writeln(" ***** Elements missing in hash[complex] table");
      okay := FALSE;
    end if;
    complexBooleanHashVar    @:= [complex(5.6, 7.8)] TRUE;
    complexIntegerHashVar    @:= [complex(5.6, 7.8)] 1234;
    complexBigIntegerHashVar @:= [complex(5.6, 7.8)] 9999999999_;
    complexFloatHashVar      @:= [complex(5.6, 7.8)] 3.1415926535;
    complexComplexHashVar    @:= [complex(5.6, 7.8)] complex(1.2, 3.4);
    complexCharHashVar       @:= [complex(5.6, 7.8)] 'Q';
    complexStringHashVar     @:= [complex(5.6, 7.8)] "success";
    complexTypeHashVar       @:= [complex(5.6, 7.8)] char;
    complexReferenceHashVar  @:= [complex(5.6, 7.8)] NIL;
    complexHashHashVar       @:= [complex(5.6, 7.8)] complexBooleanHashVar;
    if  complex(5.6, 7.8) not in complexBooleanHashVar    or
        complex(5.6, 7.8) not in complexIntegerHashVar    or
        complex(5.6, 7.8) not in complexBigIntegerHashVar or
        complex(5.6, 7.8) not in complexFloatHashVar      or
        complex(5.6, 7.8) not in complexComplexHashVar    or
        complex(5.6, 7.8) not in complexCharHashVar       or
        complex(5.6, 7.8) not in complexStringHashVar     or
        complex(5.6, 7.8) not in complexTypeHashVar       or
        complex(5.6, 7.8) not in complexReferenceHashVar  or
        complex(5.6, 7.8) not in complexHashHashVar       then
      writeln(" ***** Elements missing in hash[complex] table");
      okay := FALSE;
    end if;
    if  complexBooleanHashVar    [complex(5.6, 7.8)] <> TRUE              or
        complexIntegerHashVar    [complex(5.6, 7.8)] <> 1234              or
        complexBigIntegerHashVar [complex(5.6, 7.8)] <> 9999999999_       or
        complexFloatHashVar      [complex(5.6, 7.8)] <> 3.1415926535      or
        complexComplexHashVar    [complex(5.6, 7.8)] <> complex(1.2, 3.4) or
        complexCharHashVar       [complex(5.6, 7.8)] <> 'Q'               or
        complexStringHashVar     [complex(5.6, 7.8)] <> "success"         or
        complexTypeHashVar       [complex(5.6, 7.8)] <> char              or
        complexReferenceHashVar  [complex(5.6, 7.8)] <> NIL               then
      writeln(" ***** Elements with wrong value in hash[complex] table");
      okay := FALSE;
    end if;
    if okay then
      writeln("Hash tables with complex keys work correct.");
    else
      writeln(" ***** Hash tables with complex keys do not work correct");
      writeln;
    end if;
  end func;


const proc: chkStringHash is func
  local
    var boolean: okay is TRUE;
    var stringBooleanHash:    stringBooleanHashVar    is stringBooleanHash   .EMPTY_HASH;
    var stringIntegerHash:    stringIntegerHashVar    is stringIntegerHash   .EMPTY_HASH;
    var stringBigIntegerHash: stringBigIntegerHashVar is stringBigIntegerHash.EMPTY_HASH;
    var stringFloatHash:      stringFloatHashVar      is stringFloatHash     .EMPTY_HASH;
    var stringComplexHash:    stringComplexHashVar    is stringComplexHash   .EMPTY_HASH;
    var stringCharHash:       stringCharHashVar       is stringCharHash      .EMPTY_HASH;
    var stringStringHash:     stringStringHashVar     is stringStringHash    .EMPTY_HASH;
    var stringTypeHash:       stringTypeHashVar       is stringTypeHash      .EMPTY_HASH;
    var stringReferenceHash:  stringReferenceHashVar  is stringReferenceHash .EMPTY_HASH;
    var stringHashHash:       stringHashHashVar       is stringHashHash      .EMPTY_HASH;
  begin
    if  length(stringBooleanHashVar)    <> 0 or
        length(stringIntegerHashVar)    <> 0 or
        length(stringBigIntegerHashVar) <> 0 or
        length(stringFloatHashVar)      <> 0 or
        length(stringComplexHashVar)    <> 0 or
        length(stringCharHashVar)       <> 0 or
        length(stringStringHashVar)     <> 0 or
        length(stringTypeHashVar)       <> 0 or
        length(stringReferenceHashVar)  <> 0 or
        length(stringHashHashVar)       <> 0 then
      writeln(" ***** Number of elements in empty hash[string] table not 0");
      okay := FALSE;
    end if;
    if  "asdfghjkl" in stringBooleanHashVar    or
        "asdfghjkl" in stringIntegerHashVar    or
        "asdfghjkl" in stringBigIntegerHashVar or
        "asdfghjkl" in stringFloatHashVar      or
        "asdfghjkl" in stringComplexHashVar    or
        "asdfghjkl" in stringCharHashVar       or
        "asdfghjkl" in stringStringHashVar     or
        "asdfghjkl" in stringTypeHashVar       or
        "asdfghjkl" in stringReferenceHashVar  or
        "asdfghjkl" in stringHashHashVar       then
      writeln(" ***** Elements found in empty hash table");
      okay := FALSE;
    end if;
    stringBooleanHashVar    @:= ["asdfghjkl"] TRUE;
    stringIntegerHashVar    @:= ["asdfghjkl"] 1234;
    stringBigIntegerHashVar @:= ["asdfghjkl"] 9999999999_;
    stringFloatHashVar      @:= ["asdfghjkl"] 3.1415926535;
    stringComplexHashVar    @:= ["asdfghjkl"] complex(1.2, 3.4);
    stringCharHashVar       @:= ["asdfghjkl"] 'Q';
    stringStringHashVar     @:= ["asdfghjkl"] "success";
    stringTypeHashVar       @:= ["asdfghjkl"] char;
    stringReferenceHashVar  @:= ["asdfghjkl"] NIL;
    stringHashHashVar       @:= ["asdfghjkl"] stringBooleanHashVar;
    if  length(stringBooleanHashVar)    <> 1 or
        length(stringIntegerHashVar)    <> 1 or
        length(stringBigIntegerHashVar) <> 1 or
        length(stringFloatHashVar)      <> 1 or
        length(stringComplexHashVar)    <> 1 or
        length(stringCharHashVar)       <> 1 or
        length(stringStringHashVar)     <> 1 or
        length(stringTypeHashVar)       <> 1 or
        length(stringReferenceHashVar)  <> 1 or
        length(stringHashHashVar)       <> 1 then
      writeln(" ***** Number of elements in hash[string] table not 1");
      okay := FALSE;
    end if;
    if  "asdfghjkl" in stringBooleanHashVar    and
        "asdfghjkl" in stringIntegerHashVar    and
        "asdfghjkl" in stringBigIntegerHashVar and
        "asdfghjkl" in stringFloatHashVar      and
        "asdfghjkl" in stringComplexHashVar    and
        "asdfghjkl" in stringCharHashVar       and
        "asdfghjkl" in stringStringHashVar     and
        "asdfghjkl" in stringTypeHashVar       and
        "asdfghjkl" in stringReferenceHashVar  and
        "asdfghjkl" in stringHashHashVar       then
      noop;
    else
      writeln(" ***** Elements missing in hash[string] table");
      okay := FALSE;
    end if;
    stringBooleanHashVar    @:= ["asdfghjkl"] TRUE;
    stringIntegerHashVar    @:= ["asdfghjkl"] 1234;
    stringBigIntegerHashVar @:= ["asdfghjkl"] 9999999999_;
    stringFloatHashVar      @:= ["asdfghjkl"] 3.1415926535;
    stringComplexHashVar    @:= ["asdfghjkl"] complex(1.2, 3.4);
    stringCharHashVar       @:= ["asdfghjkl"] 'Q';
    stringStringHashVar     @:= ["asdfghjkl"] "success";
    stringTypeHashVar       @:= ["asdfghjkl"] char;
    stringReferenceHashVar  @:= ["asdfghjkl"] NIL;
    stringHashHashVar       @:= ["asdfghjkl"] stringBooleanHashVar;
    if  "asdfghjkl" not in stringBooleanHashVar    or
        "asdfghjkl" not in stringIntegerHashVar    or
        "asdfghjkl" not in stringBigIntegerHashVar or
        "asdfghjkl" not in stringFloatHashVar      or
        "asdfghjkl" not in stringComplexHashVar    or
        "asdfghjkl" not in stringCharHashVar       or
        "asdfghjkl" not in stringStringHashVar     or
        "asdfghjkl" not in stringTypeHashVar       or
        "asdfghjkl" not in stringReferenceHashVar  or
        "asdfghjkl" not in stringHashHashVar       then
      writeln(" ***** Elements missing in hash[string] table");
      okay := FALSE;
    end if;
    if  stringBooleanHashVar    ["asdfghjkl"] <> TRUE              or
        stringIntegerHashVar    ["asdfghjkl"] <> 1234              or
        stringBigIntegerHashVar ["asdfghjkl"] <> 9999999999_       or
        stringFloatHashVar      ["asdfghjkl"] <> 3.1415926535      or
        stringComplexHashVar    ["asdfghjkl"] <> complex(1.2, 3.4) or
        stringCharHashVar       ["asdfghjkl"] <> 'Q'               or
        stringStringHashVar     ["asdfghjkl"] <> "success"         or
        stringTypeHashVar       ["asdfghjkl"] <> char              or
        stringReferenceHashVar  ["asdfghjkl"] <> NIL               then
      writeln(" ***** Elements with wrong value in hash[string] table");
      okay := FALSE;
    end if;
    if okay then
      writeln("Hash tables with string keys work correct.");
    else
      writeln(" ***** Hash tables with string keys do not work correct");
      writeln;
    end if;
  end func;


const proc: chkKeysFunction is func
  local
    var boolean: okay is TRUE;
    var integerIntegerHash: aHash is integerIntegerHash.value;
    var array integer: hashKeys is 0 times 0;
    var integer: number is 0;
  begin
    for number range 1 to 50000 do
      aHash @:= [number] number;
    end for;
    hashKeys := keys(aHash);
    if length(hashKeys) <> 50000 then
      okay := FALSE;
    else
      hashKeys := sort(hashKeys);
      for number range 1 to 50000 do
        if hashKeys[number] <> number then
          okay := FALSE;
        end if;
      end for;
    end if;
    if okay then
      writeln("The keys function for hash tables works correct.");
    else
      writeln(" ***** The keys function for hash tables does not work correct.");
      writeln;
    end if;
  end func;


const proc: main is func
  begin
    writeln;
    chkBooleanHash;
    chkIntegerHash;
    chkFloatHash;
    chkComplexHash;
    chkStringHash;
    chkKeysFunction;
  end func;
